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(),

AuthorKonata <konata@posteo.jp>
Date
Commit8220e00ef6237c8deab917ad7eb9933a01a54932
Parent1245ac7
11 files changed, 173 insertions(+), 31 deletions(-)
Minclude/cutils/byte_array.h
@@ -15,7 +15,6 @@ typedef struct Bytearray
1515 size_t element_size;
1616 } Bytearray;
1717
18-#define new_bytearray(element_size) bytearray_with_capacity(BYTEARRAY_DEFAULT_SIZE, element_size)
1918 Bytearray* bytearray_with_capacity(size_t capacity, size_t element_size);
2019 void delete_bytearray(Bytearray* bytearray, void(*rmv_el) (void*));
2120
@@ -24,10 +23,8 @@ static void* bytearray_at(const Bytearray* bytearray, size_t index)
2423 {
2524 return bytearray->items+(index*bytearray->element_size);
2625 }
27-#define bytearray_pop(bytearray, retptr) bytearray_pop_at(bytearray, bytearray->length-1, retptr)
2826 void* bytearray_pop_at(Bytearray* bytearray, size_t index, void* retptr);
2927
30-#define bytearray_push(bytearray, item) bytearray_insert(bytearray, bytearray->length, item)
3128 bool bytearray_insert(Bytearray* bytearray, size_t index, const void* item);
3229
3330 HEDLEY_INLINE
@@ -52,6 +49,9 @@ bool bytearray_shrink(Bytearray* bytearray);
5249 HEDLEY_NON_NULL(3)
5350 size_t* bytearray_find(const Bytearray* haystack, const void* needle, int (*cmp)(const void*, const void*));
5451
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)
5555
5656 #endif /* CUTILS_BYTE_ARRAY_H */
5757
Minclude/cutils/cutils.h
@@ -9,5 +9,6 @@
99 #include <cutils/extensions.h>
1010 #include <cutils/backport.h>
1111 #include <cutils/bitfuncs.h>
12+#include <cutils/math.h>
1213
1314 #endif /* CUTILS_CUTILS_H */
Minclude/cutils/dyn_string.h
@@ -15,7 +15,6 @@ typedef struct String
1515 bool null_terminated;
1616 } String;
1717
18-#define new_string(null_terminated) string_with_capacity(STRING_DEFAULT_SIZE, null_terminated)
1918 String* string_with_capacity(size_t capacity, bool null_terminated);
2019 void delete_string(String* string);
2120
@@ -25,11 +24,9 @@ static char string_at(const String* string, size_t index)
2524 return string->chars[index];
2625 }
2726
28-#define string_pop(string) string_pop_at(string, string->length-1)
2927 char string_pop_at(String* string, size_t index);
3028
3129 bool string_insert(String* string, size_t index, char character);
32-#define string_push(string, character) string_insert(string, string->length, character)
3330
3431 HEDLEY_INLINE
3532 static void string_remove(String* string, size_t index)
@@ -45,17 +42,13 @@ size_t string_strip(String* string, char character);
4542
4643 bool string_grow(String* string, size_t add);
4744 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);
4946 HEDLEY_INLINE
5047 static bool string_find_str(const String* haystack, const String* needle, size_t* pos)
5148 {
5249 return cutil_memmem(haystack->chars, haystack->length, needle->chars, needle->length, pos);
5350 }
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);
5952
6053 size_t string_count(const String* string, char character);
6154
@@ -68,4 +61,8 @@ char* to_cstring(const String* string);
6861 char* to_cstring_del(String* string);
6962 void string_move(String* dest, String* src);
7063
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+
7168 #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
4747 errno = ENOMEM;
4848 return NULL;
4949 } else {
50- return cutil_reallocarray(ptr, nmemb, size+add);
50+ return cutil_reallocarray(ptr, nmemb+add, size);
5151 }
5252 }
5353
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
1414 size_t length;
1515 } Vector;
1616
17-#define new_vector() vector_with_capacity(VECTOR_DEFAULT_SIZE)
1817 Vector* vector_with_capacity(size_t capacity);
1918 void delete_vector(Vector* vector, void(*rmv) (void*));
2019
@@ -23,11 +22,9 @@ static void* vector_at(const Vector* vector, size_t index)
2322 {
2423 return vector->items[index];
2524 }
26-#define vector_pop(vector) vector_pop_at(vector, vector->length-1)
2725 void* vector_pop_at(Vector* vector, size_t index);
2826
2927 bool vector_insert(Vector* vector, size_t index, void* item);
30-#define vector_push(vector, item) vector_insert(vector, vector->length, item)
3128
3229 HEDLEY_INLINE
3330 static void vector_remove(Vector* vector, size_t index, void (*rmv)(void*))
@@ -48,5 +45,8 @@ bool vector_shrink(Vector* vector);
4845 HEDLEY_NON_NULL(3)
4946 size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const void*, const void*));
5047
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)
5151
5252 #endif /* CUTILS_VECTOR_H */
Mmeson.build
@@ -1,7 +1,7 @@
11 project('cutils', 'c')
22
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
55
66 subdir('include')
77 subdir('src')
Msrc/dyn_string.c
@@ -83,21 +83,28 @@ bool string_concat(String* string, const String* other)
8383 return true;
8484 }
8585
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)
8787 {
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)
9190 {
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;
9795 }
98- return false;
9996 }
10097
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+
101108 size_t string_count(const String* string, char character)
102109 {
103110 size_t i, ret = 0;
@@ -161,13 +168,14 @@ String* from_cstring_reuse(char* cstring, size_t capacity, bool null_terminated)
161168 {
162169 String* string;
163170
164- if(cstring)
171+ if(!cstring)
165172 return NULL;
166173
167174 string = malloc(sizeof(*string));
168175 if(!string)
169176 return NULL;
170177
178+ string->chars = cstring;
171179 string->length = strlen(cstring);
172180 string->capacity = capacity;
173181
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']
22 srctest = src + ['test.c']
33
44 cutils_lib = library('cutils', src, include_directories : inc, install: true)
Msrc/test.c
@@ -153,6 +153,13 @@ static void test_string(void)
153153 assert(strcmp(string->chars, "koasä_ #") == 0);
154154
155155 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+
156163 }
157164
158165 static void test_bytearray(void)
@@ -258,7 +265,7 @@ static void test_ll(void)
258265 {
259266 LinkedList* ll;
260267 struct test my_structa, my_structb, *my_structptr;
261- int truth;
268+ bool truth;
262269 my_structa.a = 5;
263270 my_structa.b = 5;
264271 my_structb.a = 7;
@@ -316,6 +323,7 @@ int main(int argc, char** argv)
316323 /* memswap tests */
317324 int a = 5;
318325 int b = 2;
326+ Bytearray* bt;
319327 void* tmp = malloc(sizeof(int));
320328
321329 memswap(&a, &b, sizeof(int));
@@ -348,5 +356,14 @@ int main(int argc, char** argv)
348356 assert(cutil_strcasecmp("ASD", "bsd") < 0);
349357 assert(cutil_strncasecmp("ASDn", "asd", 3) == 0);
350358 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+
351368 return 0;
352369 }