moved the convenience macros of vector/bytearray/string to bottom, added math.h/.c with isqrt(), ipow(), is_prime(), primesieve(), added tests, fixed bug in reallocarray_inc() and string_cmp, use memchr for string_find_char(),
Minclude/cutils/byte_array.h
| @@ -15,7 +15,6 @@ typedef struct Bytearray | |||
|---|---|---|---|
| 15 | 15 | size_t element_size; | |
| 16 | 16 | } Bytearray; | |
| 17 | 17 | ||
| 18 | - | #define new_bytearray(element_size) bytearray_with_capacity(BYTEARRAY_DEFAULT_SIZE, element_size) | |
| 19 | 18 | Bytearray* bytearray_with_capacity(size_t capacity, size_t element_size); | |
| 20 | 19 | void delete_bytearray(Bytearray* bytearray, void(*rmv_el) (void*)); | |
| 21 | 20 | ||
| @@ -24,10 +23,8 @@ static void* bytearray_at(const Bytearray* bytearray, size_t index) | |||
|---|---|---|---|
| 24 | 23 | { | |
| 25 | 24 | return bytearray->items+(index*bytearray->element_size); | |
| 26 | 25 | } | |
| 27 | - | #define bytearray_pop(bytearray, retptr) bytearray_pop_at(bytearray, bytearray->length-1, retptr) | |
| 28 | 26 | void* bytearray_pop_at(Bytearray* bytearray, size_t index, void* retptr); | |
| 29 | 27 | ||
| 30 | - | #define bytearray_push(bytearray, item) bytearray_insert(bytearray, bytearray->length, item) | |
| 31 | 28 | bool bytearray_insert(Bytearray* bytearray, size_t index, const void* item); | |
| 32 | 29 | ||
| 33 | 30 | HEDLEY_INLINE | |
| @@ -52,6 +49,9 @@ bool bytearray_shrink(Bytearray* bytearray); | |||
|---|---|---|---|
| 52 | 49 | HEDLEY_NON_NULL(3) | |
| 53 | 50 | size_t* bytearray_find(const Bytearray* haystack, const void* needle, int (*cmp)(const void*, const void*)); | |
| 54 | 51 | ||
| 52 | + | #define new_bytearray(element_size) bytearray_with_capacity(BYTEARRAY_DEFAULT_SIZE, element_size) | |
| 53 | + | #define bytearray_pop(bytearray, retptr) bytearray_pop_at(bytearray, bytearray->length-1, retptr) | |
| 54 | + | #define bytearray_push(bytearray, item) bytearray_insert(bytearray, bytearray->length, item) | |
| 55 | 55 | ||
| 56 | 56 | #endif /* CUTILS_BYTE_ARRAY_H */ | |
| 57 | 57 | ||
Minclude/cutils/cutils.h
| @@ -9,5 +9,6 @@ | |||
|---|---|---|---|
| 9 | 9 | #include <cutils/extensions.h> | |
| 10 | 10 | #include <cutils/backport.h> | |
| 11 | 11 | #include <cutils/bitfuncs.h> | |
| 12 | + | #include <cutils/math.h> | |
| 12 | 13 | ||
| 13 | 14 | #endif /* CUTILS_CUTILS_H */ | |
Minclude/cutils/dyn_string.h
| @@ -15,7 +15,6 @@ typedef struct String | |||
|---|---|---|---|
| 15 | 15 | bool null_terminated; | |
| 16 | 16 | } String; | |
| 17 | 17 | ||
| 18 | - | #define new_string(null_terminated) string_with_capacity(STRING_DEFAULT_SIZE, null_terminated) | |
| 19 | 18 | String* string_with_capacity(size_t capacity, bool null_terminated); | |
| 20 | 19 | void delete_string(String* string); | |
| 21 | 20 | ||
| @@ -25,11 +24,9 @@ static char string_at(const String* string, size_t index) | |||
|---|---|---|---|
| 25 | 24 | return string->chars[index]; | |
| 26 | 25 | } | |
| 27 | 26 | ||
| 28 | - | #define string_pop(string) string_pop_at(string, string->length-1) | |
| 29 | 27 | char string_pop_at(String* string, size_t index); | |
| 30 | 28 | ||
| 31 | 29 | bool string_insert(String* string, size_t index, char character); | |
| 32 | - | #define string_push(string, character) string_insert(string, string->length, character) | |
| 33 | 30 | ||
| 34 | 31 | HEDLEY_INLINE | |
| 35 | 32 | static void string_remove(String* string, size_t index) | |
| @@ -45,17 +42,13 @@ size_t string_strip(String* string, char character); | |||
|---|---|---|---|
| 45 | 42 | ||
| 46 | 43 | bool string_grow(String* string, size_t add); | |
| 47 | 44 | bool string_adjust_size(String* string, size_t size); | |
| 48 | - | bool string_find_char(const String* haystack, const char needle, size_t* pos); | |
| 45 | + | bool string_find_char(const String* haystack, char needle, size_t* pos); | |
| 49 | 46 | HEDLEY_INLINE | |
| 50 | 47 | static bool string_find_str(const String* haystack, const String* needle, size_t* pos) | |
| 51 | 48 | { | |
| 52 | 49 | return cutil_memmem(haystack->chars, haystack->length, needle->chars, needle->length, pos); | |
| 53 | 50 | } | |
| 54 | - | HEDLEY_INLINE | |
| 55 | - | static int string_cmp(const String* s1, const String* s2) | |
| 56 | - | { | |
| 57 | - | return memcmp(s1->chars, s2->chars, s1->length); | |
| 58 | - | } | |
| 51 | + | int string_cmp(const String* s1, const String* s2); | |
| 59 | 52 | ||
| 60 | 53 | size_t string_count(const String* string, char character); | |
| 61 | 54 | ||
| @@ -68,4 +61,8 @@ char* to_cstring(const String* string); | |||
|---|---|---|---|
| 68 | 61 | char* to_cstring_del(String* string); | |
| 69 | 62 | void string_move(String* dest, String* src); | |
| 70 | 63 | ||
| 64 | + | #define new_string(null_terminated) string_with_capacity(STRING_DEFAULT_SIZE, null_terminated) | |
| 65 | + | #define string_pop(string) string_pop_at(string, string->length-1) | |
| 66 | + | #define string_push(string, character) string_insert(string, string->length, character) | |
| 67 | + | ||
| 71 | 68 | #endif /* CUTILS_DYN_STRING_H */ | |
Minclude/cutils/extensions.h
| @@ -47,7 +47,7 @@ static void* cutil_reallocarray_inc(void *ptr, size_t nmemb, size_t size, size_t | |||
|---|---|---|---|
| 47 | 47 | errno = ENOMEM; | |
| 48 | 48 | return NULL; | |
| 49 | 49 | } else { | |
| 50 | - | return cutil_reallocarray(ptr, nmemb, size+add); | |
| 50 | + | return cutil_reallocarray(ptr, nmemb+add, size); | |
| 51 | 51 | } | |
| 52 | 52 | } | |
| 53 | 53 | ||
Ainclude/cutils/math.h
| @@ -0,0 +1,16 @@ | |||
|---|---|---|---|
| 1 | + | #ifndef CUTILS_MATH_H | |
| 2 | + | #define CUTILS_MATH_H | |
| 3 | + | ||
| 4 | + | #include <cutils/common.h> | |
| 5 | + | #include <cutils/byte_array.h> | |
| 6 | + | #include <cutils/bitfuncs.h> | |
| 7 | + | ||
| 8 | + | uintmax_t isqrt(uintmax_t n); | |
| 9 | + | intmax_t ipow(intmax_t base, uintmax_t exp); | |
| 10 | + | bool is_prime(uintmax_t n); | |
| 11 | + | Bytearray* primesieve(uintmax_t limit); | |
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | #endif /* CUTILS_MATH_H */ | |
| 16 | + | ||
Minclude/cutils/vector.h
| @@ -14,7 +14,6 @@ typedef struct Vector | |||
|---|---|---|---|
| 14 | 14 | size_t length; | |
| 15 | 15 | } Vector; | |
| 16 | 16 | ||
| 17 | - | #define new_vector() vector_with_capacity(VECTOR_DEFAULT_SIZE) | |
| 18 | 17 | Vector* vector_with_capacity(size_t capacity); | |
| 19 | 18 | void delete_vector(Vector* vector, void(*rmv) (void*)); | |
| 20 | 19 | ||
| @@ -23,11 +22,9 @@ static void* vector_at(const Vector* vector, size_t index) | |||
|---|---|---|---|
| 23 | 22 | { | |
| 24 | 23 | return vector->items[index]; | |
| 25 | 24 | } | |
| 26 | - | #define vector_pop(vector) vector_pop_at(vector, vector->length-1) | |
| 27 | 25 | void* vector_pop_at(Vector* vector, size_t index); | |
| 28 | 26 | ||
| 29 | 27 | bool vector_insert(Vector* vector, size_t index, void* item); | |
| 30 | - | #define vector_push(vector, item) vector_insert(vector, vector->length, item) | |
| 31 | 28 | ||
| 32 | 29 | HEDLEY_INLINE | |
| 33 | 30 | static void vector_remove(Vector* vector, size_t index, void (*rmv)(void*)) | |
| @@ -48,5 +45,8 @@ bool vector_shrink(Vector* vector); | |||
|---|---|---|---|
| 48 | 45 | HEDLEY_NON_NULL(3) | |
| 49 | 46 | size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const void*, const void*)); | |
| 50 | 47 | ||
| 48 | + | #define new_vector() vector_with_capacity(VECTOR_DEFAULT_SIZE) | |
| 49 | + | #define vector_pop(vector) vector_pop_at(vector, vector->length-1) | |
| 50 | + | #define vector_push(vector, item) vector_insert(vector, vector->length, item) | |
| 51 | 51 | ||
| 52 | 52 | #endif /* CUTILS_VECTOR_H */ | |
Mmeson.build
| @@ -1,7 +1,7 @@ | |||
|---|---|---|---|
| 1 | 1 | project('cutils', 'c') | |
| 2 | 2 | ||
| 3 | - | WARNINGS = ['-Wall', '-Wpedantic', '-Wextra', '-Wnull-dereference', '-Wshadow', '-Wconversion', '-Wstrict-prototypes', '-Wmissing-prototypes', '-Wcast-qual', '-Wstrict-overflow=5', '-Wunreachable-code', '-Wno-unused-parameter', '-Wno-unused-function'] | |
| 4 | - | CFLAGS = ['-std=c89', '-fstrict-aliasing', '-fPIC', '-Wno-long-long'] + WARNINGS | |
| 3 | + | WARNINGS = ['-Wall', '-Wpedantic', '-Wextra', '-Wnull-dereference', '-Wshadow', '-Wconversion', '-Wstrict-prototypes', '-Wmissing-prototypes', '-Wcast-qual', '-Wstrict-overflow=5', '-Wunreachable-code', '-Wno-unused-parameter', '-Wno-unused-function', '-Wno-long-long'] | |
| 4 | + | CFLAGS = ['-std=c89', '-fstrict-aliasing', '-fPIC', '-Wno-long-long', '-Og'] + WARNINGS | |
| 5 | 5 | ||
| 6 | 6 | subdir('include') | |
| 7 | 7 | subdir('src') | |
Msrc/dyn_string.c
| @@ -83,21 +83,28 @@ bool string_concat(String* string, const String* other) | |||
|---|---|---|---|
| 83 | 83 | return true; | |
| 84 | 84 | } | |
| 85 | 85 | ||
| 86 | - | bool string_find_char(const String* haystack, const char needle, size_t* pos) | |
| 86 | + | bool string_find_char(const String* haystack, char needle, size_t* pos) | |
| 87 | 87 | { | |
| 88 | - | size_t i; | |
| 89 | - | ||
| 90 | - | for(i = 0; i < haystack->length; i++) | |
| 88 | + | char* ret = memchr(haystack->chars, needle, haystack->length); | |
| 89 | + | if(!ret) | |
| 91 | 90 | { | |
| 92 | - | if(haystack->chars[i] == needle) | |
| 93 | - | { | |
| 94 | - | *pos = i; | |
| 95 | - | return true; | |
| 96 | - | } | |
| 91 | + | return false; | |
| 92 | + | } else { | |
| 93 | + | *pos = (size_t)(ret-haystack->chars); | |
| 94 | + | return true; | |
| 97 | 95 | } | |
| 98 | - | return false; | |
| 99 | 96 | } | |
| 100 | 97 | ||
| 98 | + | int string_cmp(const String* s1, const String* s2) | |
| 99 | + | { | |
| 100 | + | int ret = memcmp(s1->chars, s2->chars, s1->length < s2->length ? s1->length : s2->length); | |
| 101 | + | if(ret == 0 && s1->length != s2->length) | |
| 102 | + | return s1->length < s2->length ? -1 : 1; | |
| 103 | + | else | |
| 104 | + | return ret; | |
| 105 | + | } | |
| 106 | + | ||
| 107 | + | ||
| 101 | 108 | size_t string_count(const String* string, char character) | |
| 102 | 109 | { | |
| 103 | 110 | size_t i, ret = 0; | |
| @@ -161,13 +168,14 @@ String* from_cstring_reuse(char* cstring, size_t capacity, bool null_terminated) | |||
|---|---|---|---|
| 161 | 168 | { | |
| 162 | 169 | String* string; | |
| 163 | 170 | ||
| 164 | - | if(cstring) | |
| 171 | + | if(!cstring) | |
| 165 | 172 | return NULL; | |
| 166 | 173 | ||
| 167 | 174 | string = malloc(sizeof(*string)); | |
| 168 | 175 | if(!string) | |
| 169 | 176 | return NULL; | |
| 170 | 177 | ||
| 178 | + | string->chars = cstring; | |
| 171 | 179 | string->length = strlen(cstring); | |
| 172 | 180 | string->capacity = capacity; | |
| 173 | 181 | ||
Asrc/math.c
| @@ -0,0 +1,103 @@ | |||
|---|---|---|---|
| 1 | + | #include <cutils/math.h> | |
| 2 | + | ||
| 3 | + | uintmax_t isqrt(uintmax_t n) | |
| 4 | + | { | |
| 5 | + | uintmax_t start = 1, end = n/2, ans; | |
| 6 | + | if(n == 0 || n == 1) | |
| 7 | + | return n; | |
| 8 | + | ||
| 9 | + | while(start <= end) | |
| 10 | + | { | |
| 11 | + | uintmax_t mid = (start + end) / 2; | |
| 12 | + | ||
| 13 | + | if(mid*mid == n) | |
| 14 | + | return mid; | |
| 15 | + | ||
| 16 | + | if(mid*mid < n) | |
| 17 | + | { | |
| 18 | + | start = mid + 1; | |
| 19 | + | ans = mid; | |
| 20 | + | } else { | |
| 21 | + | end = mid - 1; | |
| 22 | + | } | |
| 23 | + | } | |
| 24 | + | return ans; | |
| 25 | + | } | |
| 26 | + | ||
| 27 | + | intmax_t ipow(intmax_t base, uintmax_t exp) | |
| 28 | + | { | |
| 29 | + | intmax_t result = 1; | |
| 30 | + | while (exp) | |
| 31 | + | { | |
| 32 | + | if (exp & 1) | |
| 33 | + | result *= base; | |
| 34 | + | exp >>= 1; | |
| 35 | + | base *= base; | |
| 36 | + | } | |
| 37 | + | ||
| 38 | + | return result; | |
| 39 | + | } | |
| 40 | + | ||
| 41 | + | bool is_prime(uintmax_t n) | |
| 42 | + | { | |
| 43 | + | uintmax_t i; | |
| 44 | + | ||
| 45 | + | if (n < 2) return false; | |
| 46 | + | if (n % 2 == 0 && n != 2) return false; | |
| 47 | + | ||
| 48 | + | for(i = 3; i < isqrt(n); i+=2) | |
| 49 | + | { | |
| 50 | + | if (n % i == 0) | |
| 51 | + | return false; | |
| 52 | + | } | |
| 53 | + | return true; | |
| 54 | + | } | |
| 55 | + | ||
| 56 | + | static void primesieve_set(byte* numbers, size_t index) | |
| 57 | + | { | |
| 58 | + | numbers[index/8] |= (byte)(1 << (index%8)); | |
| 59 | + | } | |
| 60 | + | ||
| 61 | + | static bool primesieve_get(byte* numbers, size_t index) | |
| 62 | + | { | |
| 63 | + | return getbit(byte, (numbers[index/8] >> index%8), 0); | |
| 64 | + | } | |
| 65 | + | #include <assert.h> | |
| 66 | + | Bytearray* primesieve(uintmax_t limit) | |
| 67 | + | { | |
| 68 | + | size_t i, j, length = limit/8+1; | |
| 69 | + | byte* numbers; | |
| 70 | + | Bytearray* bt; | |
| 71 | + | ||
| 72 | + | numbers = calloc(length, 1); | |
| 73 | + | if(!numbers) | |
| 74 | + | return NULL; | |
| 75 | + | ||
| 76 | + | bt = new_bytearray(sizeof(uintmax_t)); | |
| 77 | + | if(!numbers) | |
| 78 | + | { | |
| 79 | + | free(numbers); | |
| 80 | + | return NULL; | |
| 81 | + | } | |
| 82 | + | ||
| 83 | + | ||
| 84 | + | for(i = 2; i < isqrt(limit); i++) | |
| 85 | + | { | |
| 86 | + | if(primesieve_get(numbers, i) == 0) | |
| 87 | + | { | |
| 88 | + | for(j = i*i; j < limit; j+=i) | |
| 89 | + | { | |
| 90 | + | primesieve_set(numbers, j); | |
| 91 | + | } | |
| 92 | + | } | |
| 93 | + | } | |
| 94 | + | ||
| 95 | + | for(i = 0; i < limit; i++) | |
| 96 | + | { | |
| 97 | + | if(primesieve_get(numbers, i) == 0) | |
| 98 | + | bytearray_push(bt, &i); | |
| 99 | + | } | |
| 100 | + | ||
| 101 | + | free(numbers); | |
| 102 | + | return bt; | |
| 103 | + | } | |
Msrc/meson.build
| @@ -1,4 +1,4 @@ | |||
|---|---|---|---|
| 1 | - | src = ['vector.c', 'dyn_string.c', 'misc.c', 'byte_array.c', 'linked-list.c', 'extensions.c', 'bitfuncs.c'] | |
| 1 | + | src = ['vector.c', 'dyn_string.c', 'misc.c', 'byte_array.c', 'linked-list.c', 'extensions.c', 'bitfuncs.c', 'math.c'] | |
| 2 | 2 | srctest = src + ['test.c'] | |
| 3 | 3 | ||
| 4 | 4 | cutils_lib = library('cutils', src, include_directories : inc, install: true) | |
Msrc/test.c
| @@ -153,6 +153,13 @@ static void test_string(void) | |||
|---|---|---|---|
| 153 | 153 | assert(strcmp(string->chars, "koasä_ #") == 0); | |
| 154 | 154 | ||
| 155 | 155 | delete_string(string); | |
| 156 | + | ||
| 157 | + | string = from_cstring_reuse("asdasdas1", strlen("asdasdas1"), false); | |
| 158 | + | string2 = from_cstring_reuse("asdasdas", strlen("asdasdas"), false); | |
| 159 | + | assert(string_cmp(string, string2) > 0); | |
| 160 | + | free(string); | |
| 161 | + | free(string2); | |
| 162 | + | ||
| 156 | 163 | } | |
| 157 | 164 | ||
| 158 | 165 | static void test_bytearray(void) | |
| @@ -258,7 +265,7 @@ static void test_ll(void) | |||
|---|---|---|---|
| 258 | 265 | { | |
| 259 | 266 | LinkedList* ll; | |
| 260 | 267 | struct test my_structa, my_structb, *my_structptr; | |
| 261 | - | int truth; | |
| 268 | + | bool truth; | |
| 262 | 269 | my_structa.a = 5; | |
| 263 | 270 | my_structa.b = 5; | |
| 264 | 271 | my_structb.a = 7; | |
| @@ -316,6 +323,7 @@ int main(int argc, char** argv) | |||
|---|---|---|---|
| 316 | 323 | /* memswap tests */ | |
| 317 | 324 | int a = 5; | |
| 318 | 325 | int b = 2; | |
| 326 | + | Bytearray* bt; | |
| 319 | 327 | void* tmp = malloc(sizeof(int)); | |
| 320 | 328 | ||
| 321 | 329 | memswap(&a, &b, sizeof(int)); | |
| @@ -348,5 +356,14 @@ int main(int argc, char** argv) | |||
|---|---|---|---|
| 348 | 356 | assert(cutil_strcasecmp("ASD", "bsd") < 0); | |
| 349 | 357 | assert(cutil_strncasecmp("ASDn", "asd", 3) == 0); | |
| 350 | 358 | assert(cutil_strncasecmp("ASDn", "asd", 4) >0); | |
| 359 | + | ||
| 360 | + | ||
| 361 | + | assert(ipow(2,32) == 4294967296); | |
| 362 | + | assert(isqrt(123123) == 350); | |
| 363 | + | bt = primesieve(100000000); | |
| 364 | + | assert(*(uintmax_t*)bytearray_at(bt, 312312) == 4444697); | |
| 365 | + | ||
| 366 | + | delete_bytearray(bt, NULL); | |
| 367 | + | ||
| 351 | 368 | return 0; | |
| 352 | 369 | } | |