├── image └── ArraySimpleTest.png ├── test.c ├── .gitignore ├── LICENSE ├── README.md └── include ├── stack.h ├── queue.h ├── hashmap.h ├── treeset.h ├── forward_list.h ├── array.h └── darray.h /image/ArraySimpleTest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myyrakle/C-STL/HEAD/image/ArraySimpleTest.png -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "include/hashmap.h" 3 | 4 | decl_hashmap(Foo, int, int) 5 | def_hashmap(Foo, int, int) 6 | 7 | int main() 8 | { 9 | 10 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | *.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 C-STL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C-STL 2 | 3 | ![](https://img.shields.io/badge/language-C-red) ![](https://img.shields.io/badge/version-0.1.0-brightgreen) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/myyrakle/C-STL/blob/master/LICENSE) 4 | 5 | ## 소개 6 | C의 매크로 함수를 응용하여 C++의 STL(Standard Template Library)을 흉내낸 라이브러리입니다. 7 | 멤버-함수포인터를 사용하여 객체지향적 형식을 가집니다. 8 | 사용 조건은 C99입니다. C99의 몇몇 표준 라이브러리(stdbool.h 등)에 종속적입니다. 이 문제는 차후 해결할 예정에 있습니다... 9 | 10 | *** 11 | 12 | ## 라이센스 13 | 14 | 라이센스는 MIT 라이센스를 적용합니다. 15 | 막 갖다쓰셔도 됩니다. 16 | 17 | *** 18 | 19 | [레퍼런스용 위키로 이동](https://github.com/myyrakle/C-STL/wiki) 20 | 21 | *** 22 | 23 | ## 구현 현황 24 | 25 | 매크로의 목록과 현황은 아래와 같습니다. 26 | - decl_array : 컴파일타임 정적 배열(compiletime static array). 27 | - decl_darray : 런타임 고정배열(runtime dynamic fixed array). 28 | - decl_vector : 런타임 가변배열(runtime dynamic mutable array). 29 | - decl_stack : 스택(stack). 30 | - decl_queue : 큐(queue). 31 | - decl_list : 양방향 연결리스트(linked list). 32 | - decl_forward_list : 단방향 연결리스트(single linked list). 33 | - decl_circular_lisr : 원형 연결리스트(circular linked list). 구현중 34 | - decl_treeset : 트리셋(tree set). Not Implemented 35 | - decl_treemap : 트리맵(tree map). Not Implemented 36 | - decl_hashset : 해시셋(hashtable set). Not Implemented 37 | - decl_hashmap : 해시맵(hashtable map). 구현중 38 | - decl_maxheap : 최대 힙(max heap). Not Implemented 39 | - decl_minheap : 최소 힙(min heap). Not Implemented 40 | 41 | *** 42 | 43 | ## 사용례 44 | 45 | C++의 std::array에 해당하는 매크로는 decl_array, def_array 입니다. 46 | 아래와 같이 선언하면 int 타입에 길이가 10인 배열 타입이 IntArray라는 이름으로 구체화됩니다. 47 | ``` 48 | decl_array(IntArray, int, 10) 49 | def_array(IntArray, int, 10) 50 | ``` 51 | decl_XXX 는 .h파일에 들어갈 전방선언이 포함되어있습니다. 52 | def_XXX 는 .c파일에 들어갈 메서드 구현이 포함되어있습니다. def_XXX를 .h 파일에서 사용하시면 안됩니다. 53 | 54 | 55 | 그리고 객체의 생성은 아래와 같이 합니다. 꼭 new를 사용해야 하는 건 아니지만, 추천하지 않습니다. 56 | ``` 57 | IntArray arr = new_IntArray(); 58 | ``` 59 | 60 | 61 | 그리고 메서드를 사용할 때는 아래와 같이 합니다. 62 | 꼭 자기 자신의 주소를 첫번째 인자로 전달해야 합니다. 63 | ``` 64 | arr.find(&arr, 100); 65 | ``` 66 | 67 | 68 | 아래는 예시 이미지입니다. 69 | ![ArrayTest](./image/ArraySimpleTest.png) 70 | *** 71 | 72 | ## 기여자 73 | - [sean9892](https://github.com/sean9892) (스택, 큐 구현. 다방면의 피드백과 개선) 74 | -------------------------------------------------------------------------------- /include/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef C_STL_STACK_H 2 | #define C_STL_STACK_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define decl_stack(declname, type) \ 9 | \ 10 | struct declname; \ 11 | typedef struct declname declname; \ 12 | \ 13 | struct declname##_node; \ 14 | typedef struct declname##_node declname##_node; \ 15 | \ 16 | struct declname##_node \ 17 | { \ 18 | type data; \ 19 | declname##_node *bptr; \ 20 | }; \ 21 | \ 22 | struct declname \ 23 | { \ 24 | declname##_node *const tail; \ 25 | const size_t length; \ 26 | \ 27 | void (*push)(declname *, type); \ 28 | void (*push_ptr)(declname *, const type *); \ 29 | void (*pop)(declname *); \ 30 | type (*top)(const declname *); \ 31 | type *(*top_ptr)(declname *); \ 32 | const type *(*top_cptr)(const declname *); \ 33 | size_t (*size)(const declname *); \ 34 | bool (*is_empty)(const declname *); \ 35 | bool (*is_not_empty)(const declname *); \ 36 | void (*clear)(declname *); \ 37 | }; \ 38 | \ 39 | void declname##_push(declname *, type); \ 40 | void declname##_push_ptr(declname *, const type *); \ 41 | void declname##_pop(declname *); \ 42 | type declname##_top(const declname *); \ 43 | type *declname##_top_ptr(declname *); \ 44 | const type *declname##_top_cptr(const declname *); \ 45 | size_t declname##_size(const declname *); \ 46 | bool declname##_is_empty(const declname *); \ 47 | bool declname##_is_not_empty(const declname *); \ 48 | void declname##_clear(declname *); 49 | 50 | #define def_stack(declname, type) \ 51 | void declname##_push(declname *self, type d) \ 52 | { \ 53 | declname##_node *ptr = (declname##_node *)malloc(sizeof(declname##_node)); \ 54 | ptr->bptr = self->tail; \ 55 | ptr->data = d; \ 56 | (*(declname##_node **)&self->tail) = ptr; \ 57 | ++*(size_t *)&self->length; \ 58 | } \ 59 | void declname##_push_ptr(declname *self, const type *p) \ 60 | { \ 61 | declname##_node *ptr = (declname##_node *)malloc(sizeof(declname##_node)); \ 62 | ptr->bptr = self->tail; \ 63 | ptr->data = *p; \ 64 | (*(declname##_node **)&self->tail) = ptr; \ 65 | ++*(size_t *)&self->length; \ 66 | } \ 67 | \ 68 | void declname##_pop(declname *self) \ 69 | { \ 70 | assert(self->length != 0); \ 71 | declname##_node *ptr = self->tail->bptr; \ 72 | free(self->tail); \ 73 | (*(declname##_node **)&self->tail) = ptr; \ 74 | --*(size_t *)&self->length; \ 75 | } \ 76 | \ 77 | type declname##_top(const declname *self) \ 78 | { \ 79 | assert(self->length != 0); \ 80 | return self->tail->data; \ 81 | } \ 82 | \ 83 | type *declname##_top_ptr(declname *self) \ 84 | { \ 85 | assert(self->length != 0); \ 86 | return &self->tail->data; \ 87 | } \ 88 | \ 89 | const type *declname##_top_cptr(const declname *self) \ 90 | { \ 91 | assert(self->length != 0); \ 92 | return &self->tail->data; \ 93 | } \ 94 | \ 95 | size_t declname##_size(const declname *self) \ 96 | { \ 97 | return self->length; \ 98 | } \ 99 | \ 100 | bool declname##_is_empty(const declname *self) \ 101 | { \ 102 | return self->length == 0; \ 103 | } \ 104 | \ 105 | bool declname##_is_not_empty(const declname *self) \ 106 | { \ 107 | return self->length != 0; \ 108 | } \ 109 | \ 110 | void declname##_clear(declname *self) \ 111 | { \ 112 | while (declname##_is_not_empty(self)) \ 113 | declname##_pop(self); \ 114 | } \ 115 | \ 116 | declname new_##declname(void); \ 117 | \ 118 | declname new_##declname(void) \ 119 | { \ 120 | declname temp = \ 121 | { \ 122 | .push = declname##_push, \ 123 | .push_ptr = declname##_push_ptr, \ 124 | .pop = declname##_pop, \ 125 | .top = declname##_top, \ 126 | .top_ptr = declname##_top_ptr, \ 127 | .top_cptr = declname##_top_cptr, \ 128 | .is_empty = declname##_is_empty, \ 129 | .is_not_empty = declname##_is_not_empty, \ 130 | .size = declname##_size, \ 131 | .clear = declname##_clear, \ 132 | .tail = NULL, \ 133 | .length = 0}; \ 134 | return temp; \ 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /include/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef C_STL_QUEUE_H 2 | #define C_STL_QUEUE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define decl_queue(declname, type) \ 9 | \ 10 | struct declname; \ 11 | typedef struct declname declname; \ 12 | \ 13 | struct declname##_node; \ 14 | typedef struct declname##_node declname##_node; \ 15 | \ 16 | struct declname##_node \ 17 | { \ 18 | type data; \ 19 | declname##_node *next; \ 20 | }; \ 21 | \ 22 | struct declname \ 23 | { \ 24 | declname##_node *head; \ 25 | declname##_node *tail; \ 26 | size_t length; \ 27 | \ 28 | void (*push)(declname *, type); \ 29 | void (*pop)(declname *); \ 30 | size_t (*size)(const declname *); \ 31 | bool (*is_empty)(const declname *); \ 32 | bool (*is_not_empty)(const declname *); \ 33 | type (*front)(const declname *); \ 34 | type *(*front_ptr)(declname *); \ 35 | const type *(*front_cptr)(const declname *); \ 36 | void (*clear)(declname *); \ 37 | }; \ 38 | \ 39 | void declname##_push(declname *, type); \ 40 | void declname##_pop(declname *); \ 41 | size_t declname##_size(const declname *); \ 42 | bool declname##_is_empty(const declname *); \ 43 | bool declname##_is_not_empty(const declname *); \ 44 | type declname##_front(const declname *); \ 45 | type *declname##_front_ptr(declname *); \ 46 | const type *declname##_front_cptr(const declname *); \ 47 | void declname##_clear(declname *); \ 48 | \ 49 | declname new_##declname(void); 50 | 51 | #define def_queue(declname, type) \ 52 | void declname##_push(declname *self, type value) \ 53 | { \ 54 | declname##_node *node = (declname##_node *)malloc(sizeof(declname##_node)); \ 55 | node->data = value; \ 56 | node->next = NULL; \ 57 | \ 58 | if (self->tail != NULL) \ 59 | self->tail->next = node; \ 60 | self->tail = node; \ 61 | ++self->length; \ 62 | \ 63 | if (self->length == 1) \ 64 | self->head = self->tail; \ 65 | } \ 66 | \ 67 | void declname##_pop(declname *self) \ 68 | { \ 69 | assert(self->length != 0); \ 70 | \ 71 | declname##_node *temp = self->head; \ 72 | self->head = self->head->next; \ 73 | free(temp); \ 74 | --self->length; \ 75 | } \ 76 | \ 77 | size_t declname##_size(const declname *self) \ 78 | { \ 79 | return self->length; \ 80 | } \ 81 | \ 82 | bool declname##_is_empty(const declname *self) \ 83 | { \ 84 | return self->length == 0; \ 85 | } \ 86 | \ 87 | bool declname##_is_not_empty(const declname *self) \ 88 | { \ 89 | return self->length != 0; \ 90 | } \ 91 | \ 92 | type declname##_front(const declname *self) \ 93 | { \ 94 | assert(self->length != 0); \ 95 | return self->head->data; \ 96 | } \ 97 | \ 98 | type *declname##_front_ptr(declname *self) \ 99 | { \ 100 | assert(self->length != 0); \ 101 | return &self->head->data; \ 102 | } \ 103 | \ 104 | const type *declname##_front_cptr(const declname *self) \ 105 | { \ 106 | assert(self->length != 0); \ 107 | return &self->head->data; \ 108 | } \ 109 | \ 110 | void declname##_clear(declname *self) \ 111 | { \ 112 | while (0 < self->length) \ 113 | self->pop(self); \ 114 | self->head = NULL; \ 115 | self->tail = NULL; \ 116 | } \ 117 | \ 118 | declname new_##declname(void) \ 119 | { \ 120 | static declname temp = \ 121 | { \ 122 | .length = 0, \ 123 | .push = declname##_push, \ 124 | .pop = declname##_pop, \ 125 | .size = declname##_size, \ 126 | .front = declname##_front, \ 127 | .front_ptr = declname##_front_ptr, \ 128 | .front_cptr = declname##_front_cptr, \ 129 | .clear = declname##_clear, \ 130 | .is_empty = declname##_is_empty, \ 131 | .is_not_empty = declname##_is_not_empty, \ 132 | .head = NULL, \ 133 | .tail = NULL, \ 134 | }; \ 135 | return temp; \ 136 | } 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /include/hashmap.h: -------------------------------------------------------------------------------- 1 | #ifndef C_STL_HASH_MAP_H 2 | #define C_STL_HASH_MAP_H 3 | 4 | #include 5 | #include 6 | 7 | #define HASHMAP_ALLOC_DEFAULT 32 8 | 9 | // declname: type name 10 | // K: key type 11 | // V: value type 12 | // hash_function: hash function for key type. size_t(K key, size_t bucket_length) 13 | #define decl_hashmap(declname, K, V, hash_function) \ 14 | \ 15 | struct declname##_node; \ 16 | struct declname##_bucket; \ 17 | struct declname##_bucket_node; \ 18 | struct declname; \ 19 | struct declname##_iterator; \ 20 | typedef struct declname##_node declname##_node; \ 21 | typedef struct declname##_bucket declname##_bucket; \ 22 | typedef struct declname##_bucket_node declname##_bucket_node; \ 23 | typedef struct declname declname; \ 24 | typedef struct declname##_iterator declname##_iterator; \ 25 | \ 26 | /* Key-Value node type */ \ 27 | struct declname##_node \ 28 | { \ 29 | K key; \ 30 | V value; \ 31 | }; \ 32 | \ 33 | /* linked list node of each bucket */ \ 34 | struct declname##_bucket_node \ 35 | { \ 36 | declname##_node current; \ 37 | declname##_bucket_node *next; \ 38 | }; \ 39 | \ 40 | /* Bucket type identified by hashcode */ \ 41 | struct declname##_bucket \ 42 | { \ 43 | declname##_bucket_node *head; \ 44 | size_t length; \ 45 | }; \ 46 | \ 47 | struct declname##_iterator \ 48 | { \ 49 | }; \ 50 | \ 51 | struct declname \ 52 | { \ 53 | declname##_bucket *bucket_array; \ 54 | size_t bucket_length; \ 55 | size_t total_count; \ 56 | float load_factor; \ 57 | \ 58 | size_t (*bucket_count)(const declname *); \ 59 | size_t (*size)(const declname *); \ 60 | bool (*is_empty)(const declname *); \ 61 | bool (*is_not_empty)(const declname *); \ 62 | \ 63 | size_t (*clear)(declname *); \ 64 | void (*rehash)(declname *, size_t); \ 65 | \ 66 | declname##_iterator (*find)(const declname *, K); \ 67 | declname##_iterator (*find_by)(const declname *, bool (*)(const K *)); \ 68 | \ 69 | declname##_iterator (*erase)(declname *, declname##_iterator *); \ 70 | size_t (*remove)(declname *, K); \ 71 | }; 72 | 73 | // 구현부 74 | #define def_hashmap(declname, K, V, hash_function) \ 75 | /* internal function */ \ 76 | void declname##_rehash(declname *self, size_t count) \ 77 | { \ 78 | if (self->bucket_array == NULL) /*비어있으면 기본사이즈로 할당*/ \ 79 | { \ 80 | self->bucket_array = (declname##_bucket*)malloc(sizeof(declname##_bucket) * count); \ 81 | self->bucket_length = count; \ 82 | } \ 83 | else \ 84 | { \ 85 | self->bucket_array = (declname##_bucket*)realloc(self->bucket_array, sizeof(declname##_bucket) * count); \ 86 | /* TODO: 버킷 재분배 */ self->bucket_length = count; \ 87 | } \ 88 | } \ 89 | \ 90 | /* internal function */ \ 91 | void declname##_alloc_reduction(declname *self) \ 92 | { \ 93 | realloc((declname##_bucket*)self->bucket_array, self->bucket_length / 2); \ 94 | *(size_t *)&self->bucket_length /= 2; \ 95 | } \ 96 | \ 97 | bool declname##_is_empty(const declname *self) \ 98 | { \ 99 | bool is_empty = self->total_count == 0; \ 100 | return is_empty; \ 101 | } \ 102 | \ 103 | bool declname##_is_not_empty(const declname *self) \ 104 | { \ 105 | return self->total_count != 0; \ 106 | } \ 107 | \ 108 | size_t declname##_size(const declname *self) \ 109 | { \ 110 | return self->total_count; \ 111 | } \ 112 | \ 113 | size_t declname##_bucket_count(const declname *self) \ 114 | { \ 115 | return self->bucket_length; \ 116 | } \ 117 | \ 118 | size_t declname##_clear(declname *self) \ 119 | { \ 120 | return self->bucket_length; \ 121 | } \ 122 | \ 123 | declname##_iterator declname##_erase(declname *, declname##_iterator *) \ 124 | { \ 125 | declname##_iterator it; \ 126 | return it; \ 127 | } \ 128 | \ 129 | declname new_##declname(void) \ 130 | { \ 131 | static declname temp = \ 132 | { \ 133 | .bucket_array = NULL, \ 134 | .bucket_length = 64, \ 135 | .total_count = 0, \ 136 | .load_factor = 0.75, \ 137 | .bucket_count = declname##_bucket_count, \ 138 | .size = declname##_size, \ 139 | .is_empty = declname##_is_empty, \ 140 | .is_not_empty = declname##_is_not_empty, \ 141 | .clear = declname##_clear, \ 142 | .rehash = declname##_rehash, \ 143 | .erase = declname##_erase, \ 144 | }; \ 145 | \ 146 | return temp; \ 147 | } 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /include/treeset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | //디폴트 트리는 레드블랙 트리 8 | #define decl_treeset(declname, type) decl_rbtreeset(declname, type) 9 | 10 | enum _RB_Color 11 | { 12 | _RB_RED, 13 | _RB_BLACK 14 | }; 15 | 16 | //레드블랙 트리입니다. 17 | #define decl_rbtreeset(declname, type) \ 18 | \ 19 | bool declname##_default_comparer(const type *lhs, const type *rhs) \ 20 | { \ 21 | return *lhs < *rhs; \ 22 | } \ 23 | \ 24 | decl_rbtreeset_with(declname, type, declname##_default_comparer) 25 | 26 | //구현 27 | #define decl_rbtreeset_with(declname, type, comparer) \ 28 | \ 29 | struct declname; \ 30 | struct declname##_node; \ 31 | struct declname##_iterator; \ 32 | \ 33 | struct declname##_node \ 34 | { \ 35 | type data; \ 36 | declname##_node *left_child; \ 37 | declname##_node *right_child; \ 38 | _RB_Color color; \ 39 | }; \ 40 | \ 41 | struct declname##_iterator \ 42 | { \ 43 | declname##_node *ptr; \ 44 | \ 45 | void (*next)(declname##_iterator *); \ 46 | void (*prev)(declname##_iterator *); \ 47 | void (*equals)(const declname##_iterator *, const declname##_iterator *); \ 48 | }; \ 49 | \ 50 | void declname##_next(declname##_iterator *); \ 51 | void declname##_prev(declname##_iterator *); \ 52 | void declname##_equals(const declname##_iterator *, const declname##_iterator *); \ 53 | \ 54 | struct declname \ 55 | { \ 56 | declname##_node *root; \ 57 | size_t length; \ 58 | \ 59 | size_t (*size)(const declname *); /*컨테이너의 요소 수를 반환합니다.*/ \ 60 | bool (*is_empty)(const declname *); /*컨테이너가 비어있는지를 확인합니다.*/ \ 61 | bool (*is_not_empty)(const declname *); \ 62 | \ 63 | void (*clear)(declname *); /*요소를 전부 해제합니다.*/ \ 64 | \ 65 | void (*insert)(declname *, type); /*값을 새로 삽입합니다.*/ \ 66 | void (*insert_ptr)(declname *, const type *); \ 67 | \ 68 | void (*erase)(declname *, type); /*값에 해당하는 요소를 삭제합니다.*/ \ 69 | void (*erase_iter)(declname *, declname##_iterator); /*반복자를 받아 삭제합니다.*/ \ 70 | void (*erase_range)(declname *, declname##_iterator, declname##_iterator); /*반복자 범위를 삭제합니다.*/ \ 71 | \ 72 | /*특정 값의 포함 여부를 확인합니다.*/ \ 73 | bool (*contains)(const declname *, type); \ 74 | bool (*contains_ptr)(const declname *, const type *); \ 75 | \ 76 | /*특정 값을 탐색해 반복자를 반환합니다. */ \ 77 | declname##_iterator (*find)(const declname *, type); \ 78 | declname##_iterator (*find_ptr)(const declname *, const type *); \ 79 | \ 80 | declname##_iterator (*begin)(const declname *); \ 81 | declname##_iterator (*end)(const declname *); \ 82 | \ 83 | void (*for_each)(const declname *, void (*)(type)); \ 84 | void (*for_each_ptr)(declname *, void (*)(type *)); \ 85 | void (*for_each_cptr)(const declname *, void (*)(const type *)); \ 86 | }; \ 87 | \ 88 | size_t declname##_size(const declname *); \ 89 | bool declname##_is_empty(const declname *); \ 90 | bool declname##_is_not_empty(const declname *); \ 91 | void declname##_clear(declname *); \ 92 | void declname##_insert(declname *, type); \ 93 | void declname##_insert_ptr(declname *, const type *); \ 94 | void declname##_erase(declname *, type); \ 95 | void declname##_erase_iter(declname *, declname##_iterator); \ 96 | void declname##_erase_range(declname *, declname##_iterator, declname##_iterator); \ 97 | bool declname##_contains(const declname *, type); \ 98 | bool declname##_contains_ptr(const declname *, const type *); \ 99 | declname##_iterator declname##_find(const declname *, type); \ 100 | declname##_iterator declname##_find_ptr(const declname *, const type *); \ 101 | declname##_iterator declname##_begin(const declname *); \ 102 | declname##_iterator declname##_end(const declname *); \ 103 | void declname##_for_each(const declname *, void (*)(type)); \ 104 | void declname##_for_each_ptr(declname *, void (*)(type *)); \ 105 | void declname##_for_each_cptr(const declname *, void (*)(const type *)); \ 106 | \ 107 | inline declname make_##declname(); \ 108 | \ 109 | inline declname make_##declname() \ 110 | { \ 111 | declname temp = \ 112 | { \ 113 | .root = NULL, \ 114 | .size = declname##_size, \ 115 | .is_empty = declname##_is_empty, \ 116 | .is_not_empty = declname##_is_not_empty, \ 117 | .clear = declname##_clear, \ 118 | .insert = declname##_insert, \ 119 | .insert_ptr = declname##_insert_ptr, \ 120 | .erase = declname##_erase, \ 121 | .erase_iter = declname##_erase_iter, \ 122 | .erase_range = declname##_erase_range, \ 123 | .contains = declname##_contains, \ 124 | .contains_ptr = declname##_contains_ptr, \ 125 | .find = declname##_iterator declname##_find, \ 126 | .find_ptr = declname##_iterator declname##_find_ptr, \ 127 | .begin = declname##_iterator declname##_begin, \ 128 | .end = declname##_iterator declname##_end, \ 129 | .for_each = declname##_for_each, \ 130 | .for_each_ptr = declname##_for_each_ptr, \ 131 | .for_each_cptr = declname##_for_each_cptr}; \ 132 | return temp; \ 133 | } \ 134 | \ -------------------------------------------------------------------------------- /include/forward_list.h: -------------------------------------------------------------------------------- 1 | #ifndef C_STL_FORWARD_LIST_H 2 | #define C_STL_FORWARD_LIST_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | //매크로로 확장되는, 단방향 연결리스트 유사템플릿입니다. 9 | //단방향 연결리스트의 유사클래스 선언을 생성합니다. 10 | #define decl_forward_list(declname, type) \ 11 | \ 12 | /*단방향 리스트 유사클래스 전방선언이오*/ \ 13 | struct declname; \ 14 | typedef struct declname declname; \ 15 | \ 16 | /*단방향 리스트의 노드 타입이오*/ \ 17 | struct declname##_node; \ 18 | typedef struct declname##_node declname##_node; \ 19 | \ 20 | /*전용 반복자 유사클래스 전방선언이오*/ \ 21 | struct declname##_iterator; \ 22 | typedef struct declname##_iterator declname##_iterator; \ 23 | \ 24 | /*반복자 유사클래스*/ \ 25 | struct declname##_iterator \ 26 | { \ 27 | declname##_node *ptr; \ 28 | \ 29 | /*반복을 수행하오*/ \ 30 | void (*next)(declname##_iterator *); \ 31 | /*값이나 그 포인터를 가져오는 것이오*/ \ 32 | type (*get)(const declname##_iterator *); \ 33 | type *(*get_ptr)(declname##_iterator *); \ 34 | const type *(*get_cptr)(const declname##_iterator *); \ 35 | \ 36 | /*두 반복자를 비교할진저!*/ \ 37 | bool (*equals)(const declname##_iterator *, const declname##_iterator *); \ 38 | }; \ 39 | /*나는 이것을 메서드의 [선언]이라 칭하겠노라.*/ \ 40 | void declname##_iterator_next(declname##_iterator *); \ 41 | type declname##_iterator_get(const declname##_iterator *); \ 42 | type *declname##_iterator_get_ptr(declname##_iterator *); \ 43 | const type *declname##_iterator_get_cptr(const declname##_iterator *); \ 44 | bool declname##_iterator_equals(const declname##_iterator *, const declname##_iterator *); \ 45 | /*비멤버 make 함수요*/ declname##_iterator new_##declname##_iterator(declname##_node *); \ 46 | \ 47 | struct declname##_node \ 48 | { \ 49 | type value; /*값입니다..*/ \ 50 | declname##_node *next; /*다음 포인터입니다.*/ \ 51 | }; \ 52 | \ 53 | /*실체화되는 연결리스트 유사클래스요*/ \ 54 | struct declname \ 55 | { \ 56 | declname##_node *const head; \ 57 | const size_t length; \ 58 | \ 59 | /*객체를 깨끗이 비운다오*/ \ 60 | void (*clear)(declname *); \ 61 | size_t (*size)(const declname *); \ 62 | \ 63 | /*비어있는지 여부를 확인하오*/ \ 64 | bool (*is_empty)(const declname *); \ 65 | bool (*is_not_empty)(const declname *); \ 66 | \ 67 | /*앞에서 접근을 하오*/ \ 68 | type (*front)(const declname *); \ 69 | type *(*front_ptr)(declname *); \ 70 | const type *(*front_cptr)(const declname *); \ 71 | void (*push_front)(declname *, type); \ 72 | void (*pop_front)(declname *); \ 73 | \ 74 | /*특정 반복자 위치 뒤에 값과 함께 노드를 추가하오*/ \ 75 | declname##_iterator (*insert_after)(declname *, declname##_iterator *, const type *); \ 76 | \ 77 | /*반복자를 받아서 그 뒤를 삭제*/ \ 78 | declname##_iterator (*erase_after)(declname *, declname##_iterator *); \ 79 | declname##_iterator (*erase_range)(declname *, declname##_iterator *, declname##_iterator *); \ 80 | \ 81 | /*값에 대응하는 노드 삭제*/ \ 82 | void (*remove)(declname *, type); \ 83 | void (*remove_by)(declname *, bool (*)(const type *)); \ 84 | \ 85 | /*반복자를 반환하오*/ \ 86 | declname##_iterator (*begin)(declname *); \ 87 | declname##_iterator (*end)(declname *); \ 88 | \ 89 | /*선형탐색 후 찾은 위치의 반복자를 반환하오*/ \ 90 | declname##_iterator (*find)(const declname *, const type); \ 91 | declname##_iterator (*find_by)(const declname *, bool (*)(const type *)); \ 92 | \ 93 | /*선형탐색으로 포함 여부를 확인하오*/ \ 94 | bool (*contains)(const declname *, const type); \ 95 | bool (*contains_by)(const declname *, bool (*)(const type *)); \ 96 | \ 97 | /*콜백함수를 받아서 범위기반 루프를 도는 것이오*/ \ 98 | void (*for_each)(const declname *, void (*)(type)); \ 99 | void (*for_each_ptr)(declname *, void (*)(type *)); \ 100 | void (*for_each_cptr)(const declname *, void (*)(const type *)); \ 101 | }; \ 102 | /*메서드 선언이오*/ \ 103 | void declname##_clear(declname *); \ 104 | bool declname##_is_empty(const declname *); \ 105 | bool declname##_is_not_empty(const declname *); \ 106 | type declname##_front(const declname *); \ 107 | type *declname##_front_ptr(declname *); \ 108 | const type *declname##_front_cptr(const declname *); \ 109 | void declname##_push_front(declname *, type); \ 110 | void declname##_pop_front(declname *); \ 111 | declname##_iterator declname##_insert_after(declname *, declname##_iterator *, const type *); \ 112 | declname##_iterator declname##_erase_after(declname *, declname##_iterator *); \ 113 | declname##_iterator declname##_erase_range(declname *, declname##_iterator *, declname##_iterator *); \ 114 | void declname##_remove(declname *, type); \ 115 | void declname##_remove_by(declname *, bool (*)(const type *)); \ 116 | size_t declname##_size(const declname *); \ 117 | declname##_iterator declname##_begin(declname *); \ 118 | declname##_iterator declname##_end(declname *); \ 119 | declname##_iterator declname##_find(const declname *, const type); \ 120 | declname##_iterator declname##_find_by(const declname *, bool (*)(const type *)); \ 121 | bool declname##_contains(const declname *, const type); \ 122 | bool declname##_contains_by(const declname *, bool (*)(const type *)); \ 123 | void declname##_for_each(const declname *, void (*)(type)); \ 124 | void declname##_for_each_ptr(declname *, void (*)(type *)); \ 125 | void declname##_for_each_cptr(const declname *, void (*)(const type *)); \ 126 | /*비멤버 함수요*/ \ 127 | declname new_##declname(void); 128 | 129 | //단방향 연결리스트의 유사클래스 구현을 생성합니다. 130 | #define def_forward_list(declname, type) \ 131 | \ 132 | /*이것이 바로... [정의]란 것이다...*/ \ 133 | \ 134 | declname##_node *declname##_new_node(const type *v, declname##_node *next) \ 135 | { \ 136 | declname##_node *temp = malloc(sizeof(declname##_node)); \ 137 | temp->value = *v; \ 138 | temp->next = next; \ 139 | return temp; \ 140 | } \ 141 | \ 142 | void declname##_clear(declname *self) \ 143 | { \ 144 | assert(self != NULL); \ 145 | while (self->head != NULL) \ 146 | declname##_pop_front(self); \ 147 | } \ 148 | \ 149 | bool declname##_is_empty(const declname *self) \ 150 | { \ 151 | assert(self != NULL); \ 152 | return self->head == NULL; \ 153 | } \ 154 | \ 155 | bool declname##_is_not_empty(const declname *self) \ 156 | { \ 157 | assert(self != NULL); \ 158 | return self->head != NULL; \ 159 | } \ 160 | \ 161 | type declname##_front(const declname *self) \ 162 | { \ 163 | assert(self != NULL); \ 164 | assert(self->head != NULL); \ 165 | return self->head->value; \ 166 | } \ 167 | \ 168 | type *declname##_front_ptr(declname *self) \ 169 | { \ 170 | assert(self != NULL); \ 171 | assert(self->head != NULL); \ 172 | return &(self->head->value); \ 173 | } \ 174 | \ 175 | const type *declname##_front_cptr(const declname *self) \ 176 | { \ 177 | assert(self != NULL); \ 178 | assert(self->head != NULL); \ 179 | return &(self->head->value); \ 180 | } \ 181 | \ 182 | void declname##_push_front(declname *self, type v) \ 183 | { \ 184 | *(declname##_node **)&self->head = declname##_new_node(&v, self->head); \ 185 | ++*(size_t *)&self->length; \ 186 | } \ 187 | \ 188 | void declname##_pop_front(declname *self) \ 189 | { \ 190 | assert(self != NULL); \ 191 | assert(self->head != NULL); \ 192 | \ 193 | declname##_node *temp = self->head; \ 194 | if (self->head->next != NULL) \ 195 | *(declname##_node **)&self->head = self->head->next; \ 196 | free(temp); \ 197 | --*(size_t *)&self->length; \ 198 | } \ 199 | \ 200 | declname##_iterator declname##_insert_after(declname *self, declname##_iterator *pos, const type *v) \ 201 | { \ 202 | assert(pos->ptr != NULL); \ 203 | if (pos->ptr != NULL) \ 204 | { \ 205 | declname##_node *after = pos->ptr->next; \ 206 | after = declname##_new_node(v, after->next); \ 207 | return new_##declname##_iterator(after); \ 208 | } \ 209 | else \ 210 | return declname##_end(self); \ 211 | } \ 212 | \ 213 | declname##_iterator declname##_erase_after(declname *self, declname##_iterator *pos) \ 214 | { \ 215 | assert(pos->ptr != NULL); \ 216 | declname##_node *after = pos->ptr->next; \ 217 | assert(after != NULL); \ 218 | pos->ptr->next = after->next; \ 219 | free(after); \ 220 | return new_##declname##_iterator(after->next); \ 221 | } \ 222 | \ 223 | declname##_iterator declname##_erase_range(declname *self, declname##_iterator *begin, declname##_iterator *end) \ 224 | { \ 225 | assert(begin->ptr != NULL); \ 226 | declname##_node *before = begin->ptr; \ 227 | declname##_node *after = end->ptr; \ 228 | before->next = after; \ 229 | declname##_iterator_next(begin); \ 230 | while (!declname##_iterator_equals(begin, end)) \ 231 | { \ 232 | free(begin->ptr); \ 233 | declname##_iterator_next(begin); \ 234 | } \ 235 | \ 236 | return new_##declname##_iterator(after); \ 237 | } \ 238 | \ 239 | void declname##_remove(declname *self, type v) \ 240 | { \ 241 | declname##_node *current_pos = self->head; \ 242 | declname##_node *before = NULL; \ 243 | while (current_pos != NULL) \ 244 | { \ 245 | if (current_pos->value == v) \ 246 | { \ 247 | if (before != NULL) \ 248 | before->next = current_pos->next; \ 249 | free(current_pos); \ 250 | } \ 251 | \ 252 | before = current_pos; \ 253 | current_pos = current_pos->next; \ 254 | } \ 255 | } \ 256 | \ 257 | void declname##_remove_by(declname *self, bool (*eq)(const type *)) \ 258 | { \ 259 | declname##_node *current_pos = self->head; \ 260 | declname##_node *before = NULL; \ 261 | while (current_pos != NULL) \ 262 | { \ 263 | if (eq(¤t_pos->value)) \ 264 | { \ 265 | if (before != NULL) \ 266 | before->next = current_pos->next; \ 267 | free(current_pos); \ 268 | } \ 269 | \ 270 | before = current_pos; \ 271 | current_pos = current_pos->next; \ 272 | } \ 273 | } \ 274 | \ 275 | size_t declname##_size(const declname *self) \ 276 | { \ 277 | return self->length; \ 278 | } \ 279 | \ 280 | declname##_iterator declname##_begin(declname *self) \ 281 | { \ 282 | return new_##declname##_iterator(self->head); \ 283 | } \ 284 | \ 285 | declname##_iterator declname##_end(declname *self) \ 286 | { \ 287 | return new_##declname##_iterator(NULL); \ 288 | } \ 289 | \ 290 | declname##_iterator declname##_find(const declname *self, const type key) \ 291 | { \ 292 | const declname##_node *current_pos = self->head; \ 293 | while (current_pos != NULL) \ 294 | if (current_pos->value == key) \ 295 | return new_##declname##_iterator((declname##_node *)current_pos); \ 296 | else \ 297 | current_pos = current_pos->next; \ 298 | \ 299 | return self->end((declname *)&self); \ 300 | } \ 301 | \ 302 | declname##_iterator declname##_find_by(const declname *self, bool (*eq)(const type *)) \ 303 | { \ 304 | const declname##_node *current_pos = self->head; \ 305 | while (current_pos != NULL) \ 306 | if (eq(¤t_pos->value)) \ 307 | return new_##declname##_iterator((declname##_node *)current_pos); \ 308 | else \ 309 | current_pos = current_pos->next; \ 310 | \ 311 | return self->end((declname *)&self); \ 312 | } \ 313 | \ 314 | int declname##_comparer(const void *lhs, const void *rhs) \ 315 | { \ 316 | return *(type *)lhs - *(type *)rhs; \ 317 | } \ 318 | \ 319 | bool declname##_contains(const declname *self, const type key) \ 320 | { \ 321 | const declname##_node *current_pos = self->head; \ 322 | while (current_pos != NULL) \ 323 | if (current_pos->value == key) \ 324 | return true; \ 325 | else \ 326 | current_pos = current_pos->next; \ 327 | \ 328 | return false; \ 329 | } \ 330 | \ 331 | bool declname##_contains_by(const declname *self, bool (*eq)(const type *)) \ 332 | { \ 333 | const declname##_node *current_pos = self->head; \ 334 | while (current_pos != NULL) \ 335 | if (eq(¤t_pos->value)) \ 336 | return true; \ 337 | else \ 338 | current_pos = current_pos->next; \ 339 | \ 340 | return false; \ 341 | } \ 342 | \ 343 | void declname##_for_each(const declname *self, void (*f)(type)) \ 344 | { \ 345 | const declname##_node *current_pos = self->head; \ 346 | while (current_pos != NULL) \ 347 | { \ 348 | f(current_pos->value); \ 349 | current_pos = current_pos->next; \ 350 | } \ 351 | } \ 352 | \ 353 | void declname##_for_each_ptr(declname *self, void (*f)(type *)) \ 354 | { \ 355 | declname##_node *current_pos = self->head; \ 356 | while (current_pos != NULL) \ 357 | { \ 358 | f(¤t_pos->value); \ 359 | current_pos = current_pos->next; \ 360 | } \ 361 | } \ 362 | \ 363 | void declname##_for_each_cptr(const declname *self, void (*f)(const type *)) \ 364 | { \ 365 | const declname##_node *current_pos = self->head; \ 366 | while (current_pos != NULL) \ 367 | { \ 368 | f(¤t_pos->value); \ 369 | current_pos = current_pos->next; \ 370 | } \ 371 | } \ 372 | \ 373 | declname new_##declname(void) \ 374 | { \ 375 | static declname temp = \ 376 | { \ 377 | .head = NULL, \ 378 | .length = 0, \ 379 | .clear = declname##_clear, \ 380 | .is_empty = declname##_is_empty, \ 381 | .is_not_empty = declname##_is_not_empty, \ 382 | .front = declname##_front, \ 383 | .front_ptr = declname##_front_ptr, \ 384 | .front_cptr = declname##_front_cptr, \ 385 | .push_front = declname##_push_front, \ 386 | .pop_front = declname##_pop_front, \ 387 | .insert_after = declname##_insert_after, \ 388 | .erase_after = declname##_erase_after, \ 389 | .erase_range = declname##_erase_range, \ 390 | .remove = declname##_remove, \ 391 | .remove_by = declname##_remove_by, \ 392 | .size = declname##_size, \ 393 | .begin = declname##_begin, \ 394 | .end = declname##_end, \ 395 | .find = declname##_find, \ 396 | .find_by = declname##_find_by, \ 397 | .contains = declname##_contains, \ 398 | .contains_by = declname##_contains_by, \ 399 | .for_each = declname##_for_each, \ 400 | .for_each_ptr = declname##_for_each_ptr, \ 401 | .for_each_cptr = declname##_for_each_cptr}; \ 402 | return temp; \ 403 | } \ 404 | \ 405 | /*이제부터 반복자 메서드 정의요*/ \ 406 | void declname##_iterator_next(declname##_iterator *self) \ 407 | { \ 408 | assert(self->ptr != NULL); \ 409 | if (self->ptr->next != NULL) \ 410 | self->ptr = self->ptr->next; \ 411 | } \ 412 | \ 413 | type declname##_iterator_get(const declname##_iterator *self) \ 414 | { \ 415 | assert(self->ptr != NULL); \ 416 | return self->ptr->value; \ 417 | } \ 418 | type *declname##_iterator_get_ptr(declname##_iterator *self) \ 419 | { \ 420 | assert(self->ptr != NULL); \ 421 | return &(self->ptr->value); \ 422 | } \ 423 | const type *declname##_iterator_get_cptr(const declname##_iterator *self) \ 424 | { \ 425 | assert(self->ptr != NULL); \ 426 | return &(self->ptr->value); \ 427 | } \ 428 | \ 429 | bool declname##_iterator_equals(const declname##_iterator *self, const declname##_iterator *other) \ 430 | { \ 431 | return self->ptr == other->ptr; \ 432 | } \ 433 | \ 434 | declname##_iterator new_##declname##_iterator(declname##_node *p) \ 435 | { \ 436 | static declname##_iterator it = \ 437 | { \ 438 | .ptr = NULL, \ 439 | .next = declname##_iterator_next, \ 440 | .get = declname##_iterator_get, \ 441 | .get_ptr = declname##_iterator_get_ptr, \ 442 | .get_cptr = declname##_iterator_get_cptr, \ 443 | .equals = declname##_iterator_equals, \ 444 | }; \ 445 | it.ptr = p; \ 446 | return it; \ 447 | } 448 | 449 | #endif -------------------------------------------------------------------------------- /include/array.h: -------------------------------------------------------------------------------- 1 | #ifndef C_STL_ARRAY_H 2 | #define C_STL_ARRAY_H 3 | 4 | #include 5 | #include 6 | 7 | typedef int (*QsortCompare)(const void*, const void*); 8 | 9 | // TypeName: type name 10 | // T: element type 11 | // Length: Length of array 12 | #define decl_array(TypeName, T, Length) \ 13 | \ 14 | /* prototypes */ \ 15 | struct TypeName; \ 16 | typedef struct TypeName TypeName; \ 17 | struct TypeName##_iterator; \ 18 | typedef struct TypeName##_iterator TypeName##_iterator; \ 19 | \ 20 | typedef int (*TypeName##_Compare)(const T *, const T *); \ 21 | typedef int (*TypeName##_Find)(const T *); \ 22 | \ 23 | /* iterator of container */ \ 24 | struct TypeName##_iterator \ 25 | { \ 26 | T *ptr; \ 27 | \ 28 | /* iterate */ \ 29 | void (*next)(TypeName##_iterator *); \ 30 | void (*prev)(TypeName##_iterator *); \ 31 | \ 32 | /* get value */ \ 33 | T (*get)(const TypeName##_iterator *); \ 34 | T *(*get_ptr)(TypeName##_iterator *); \ 35 | \ 36 | /* value comparison */ \ 37 | bool (*equals)(const TypeName##_iterator *, const TypeName##_iterator *); \ 38 | }; \ 39 | \ 40 | /* method definition */ \ 41 | void TypeName##_iterator_next(TypeName##_iterator *); \ 42 | void TypeName##_iterator_prev(TypeName##_iterator *); \ 43 | T TypeName##_iterator_get(const TypeName##_iterator *); \ 44 | T* TypeName##_iterator_get_ptr(TypeName##_iterator *); \ 45 | bool TypeName##_iterator_equals(const TypeName##_iterator *, const TypeName##_iterator *); \ 46 | /* constructor function */ \ 47 | TypeName##_iterator new_##TypeName##_iterator(T *); \ 48 | \ 49 | /* container definition */ \ 50 | struct TypeName \ 51 | { \ 52 | T data[Length]; \ 53 | \ 54 | /* get size of array */ \ 55 | size_t (*size)(const TypeName *); \ 56 | \ 57 | /* get element of array */ \ 58 | T (*get)(const TypeName *, size_t); \ 59 | T *(*get_ptr)(TypeName *, size_t); \ 60 | const T *(*get_cptr)(const TypeName *, size_t); \ 61 | \ 62 | /* Returns a copy of the array */ \ 63 | TypeName (*clone)(const TypeName *); \ 64 | \ 65 | /* iterator */ \ 66 | TypeName##_iterator (*begin)(TypeName *); \ 67 | TypeName##_iterator (*end)(TypeName *); \ 68 | \ 69 | /* Returns an iterator of the position found after linear search */ \ 70 | TypeName##_iterator (*find)(const TypeName *, const T); \ 71 | TypeName##_iterator (*find_by)(const TypeName *, int (*)(const T *)); \ 72 | \ 73 | /* Returns the corresponding index after linear search */ \ 74 | size_t (*indexof)(const TypeName *, const T); \ 75 | size_t (*indexof_by)(const TypeName *, TypeName##_Find); \ 76 | \ 77 | /* Check for inclusion by linear search */ \ 78 | bool (*contains)(const TypeName *, const T); \ 79 | bool (*contains_by)(const TypeName *, TypeName##_Find); \ 80 | \ 81 | /* Returns an iterator of the position found after binary search */ \ 82 | TypeName##_iterator (*bfind)(const TypeName *, const T); \ 83 | TypeName##_iterator (*bfind_by)(const TypeName *, const T *, TypeName##_Compare); \ 84 | \ 85 | /* Returns the corresponding index after binary search */ \ 86 | size_t (*bindexof)(const TypeName *, const T); \ 87 | size_t (*bindexof_by)(const TypeName *, const T *, TypeName##_Compare); \ 88 | \ 89 | /* Check for inclusion with binary search */ \ 90 | bool (*bcontains)(const TypeName *, const T); \ 91 | bool (*bcontains_by)(const TypeName *, const T *, TypeName##_Compare); \ 92 | \ 93 | /* Fill an array with its value or a pointer to a value */ \ 94 | void (*fill)(TypeName *, const T); \ 95 | void (*fill_ptr)(TypeName *, const T *); \ 96 | \ 97 | /* sort */ \ 98 | void (*sort)(TypeName *); \ 99 | void (*sort_by)(TypeName *, TypeName##_Compare); \ 100 | \ 101 | /* Receive a callback function and run a range-based loop. */ \ 102 | void (*for_each)(const TypeName *, void (*)(const T)); \ 103 | void (*for_each_ptr)(TypeName *, void (*)(T *)); \ 104 | void (*for_each_cptr)(const TypeName *, void (*)(const T *)); \ 105 | }; \ 106 | \ 107 | /* method prototype */ \ 108 | size_t TypeName##_size(const TypeName *); \ 109 | T TypeName##_get(const TypeName *, size_t); \ 110 | T *TypeName##_get_ptr(TypeName *, size_t); \ 111 | const T *TypeName##_get_cptr(const TypeName *, size_t); \ 112 | TypeName TypeName##_clone(const TypeName *); \ 113 | TypeName##_iterator TypeName##_begin(TypeName *); \ 114 | TypeName##_iterator TypeName##_end(TypeName *); \ 115 | TypeName##_iterator TypeName##_find(const TypeName *, const T); \ 116 | TypeName##_iterator TypeName##_find_by(const TypeName *, TypeName##_Find); \ 117 | size_t TypeName##_indexof(const TypeName *, const T); \ 118 | size_t TypeName##_indexof_by(const TypeName *, TypeName##_Find); \ 119 | bool TypeName##_contains(const TypeName *, const T); \ 120 | bool TypeName##_contains_by(const TypeName *, TypeName##_Find); \ 121 | TypeName##_iterator TypeName##_bfind(const TypeName *, const T); \ 122 | TypeName##_iterator TypeName##_bfind_by(const TypeName *, const T *, TypeName##_Compare); \ 123 | size_t TypeName##_bindexof(const TypeName *, const T); \ 124 | size_t TypeName##_bindexof_by(const TypeName *, const T *, TypeName##_Compare); \ 125 | bool TypeName##_bcontains(const TypeName *, const T); \ 126 | bool TypeName##_bcontains_by(const TypeName *, const T *, TypeName##_Compare); \ 127 | void TypeName##_fill(TypeName *, const T); \ 128 | void TypeName##_fill_ptr(TypeName *, const T *); \ 129 | void TypeName##_sort(TypeName *); \ 130 | void TypeName##_sort_by(TypeName *, TypeName##_Compare); \ 131 | void TypeName##_for_each(const TypeName *, void (*)(const T)); \ 132 | void TypeName##_for_each_ptr(TypeName *, void (*)(T *)); \ 133 | void TypeName##_for_each_cptr(const TypeName *, void (*)(const T *)); \ 134 | /* non-member functions prototype */ \ 135 | TypeName new_##TypeName(void); 136 | 137 | // container definition 138 | #define def_array(TypeName, T, Length) \ 139 | \ 140 | size_t TypeName##_size(const TypeName *self) \ 141 | { \ 142 | return Length; \ 143 | } \ 144 | \ 145 | T TypeName##_get(const TypeName *self, size_t index) \ 146 | { \ 147 | return self->data[index]; \ 148 | } \ 149 | \ 150 | T *TypeName##_get_ptr(TypeName *self, size_t index) \ 151 | { \ 152 | return &(self->data[index]); \ 153 | } \ 154 | \ 155 | const T *TypeName##_get_cptr(const TypeName *self, size_t index) \ 156 | { \ 157 | return &(self->data[index]); \ 158 | } \ 159 | \ 160 | int TypeName##_comparer(const void *lhs, const void *rhs) \ 161 | { \ 162 | return *(T *)lhs - *(T *)rhs; \ 163 | } \ 164 | \ 165 | void TypeName##_sort(TypeName *self) \ 166 | { \ 167 | qsort(self->data, Length, sizeof(T), (QsortCompare)TypeName##_comparer); \ 168 | } \ 169 | \ 170 | void TypeName##_sort_by(TypeName *self, TypeName##_Compare comp) \ 171 | { \ 172 | qsort(self->data, Length, sizeof(T), ((QsortCompare)comp)); \ 173 | } \ 174 | \ 175 | TypeName TypeName##_clone(const TypeName *self) \ 176 | { \ 177 | TypeName temp = new_##TypeName(); \ 178 | for (int i = 0; i < Length; ++i) \ 179 | temp.data[i] = self->data[i]; \ 180 | return temp; \ 181 | } \ 182 | \ 183 | TypeName##_iterator TypeName##_begin(TypeName *self) \ 184 | { \ 185 | return new_##TypeName##_iterator(self->data); \ 186 | } \ 187 | \ 188 | TypeName##_iterator TypeName##_end(TypeName *self) \ 189 | { \ 190 | return new_##TypeName##_iterator(self->data + Length); \ 191 | } \ 192 | \ 193 | void TypeName##_fill(TypeName *self, const T value) \ 194 | { \ 195 | for (int i = 0; i < Length; ++i) \ 196 | self->data[i] = value; \ 197 | } \ 198 | \ 199 | void TypeName##_fill_ptr(TypeName *self, const T *value) \ 200 | { \ 201 | for (int i = 0; i < Length; ++i) \ 202 | self->data[i] = *value; \ 203 | } \ 204 | \ 205 | TypeName##_iterator TypeName##_find(const TypeName *self, const T key) \ 206 | { \ 207 | for (int i = 0; i < Length; ++i) \ 208 | if (self->data[i] == key) \ 209 | return new_##TypeName##_iterator((T *)&(self->data[i])); \ 210 | \ 211 | return self->end((TypeName *)&self); \ 212 | } \ 213 | \ 214 | TypeName##_iterator TypeName##_find_by(const TypeName *self, TypeName##_Find comp) \ 215 | { \ 216 | for (int i = 0; i < Length; ++i) \ 217 | if (comp(&self->data[i])) \ 218 | return new_##TypeName##_iterator((T *)&(self->data[i])); \ 219 | \ 220 | return self->end((TypeName *)&self); \ 221 | } \ 222 | \ 223 | TypeName##_iterator TypeName##_bfind(const TypeName *self, const T key) \ 224 | { \ 225 | T *p = (T*)bsearch(&key, self->data, Length, sizeof(T), TypeName##_comparer); \ 226 | if (self->data <= p && p <= &(self->data[Length - 1])) \ 227 | return new_##TypeName##_iterator(p); \ 228 | return self->end((TypeName *)&self); \ 229 | } \ 230 | \ 231 | int TypeName##_bsearch(const TypeName *self, const T *key, TypeName##_Compare comp) \ 232 | { \ 233 | int head = 0; \ 234 | int tail = Length - 1; \ 235 | int middle; \ 236 | \ 237 | while (1) \ 238 | { \ 239 | int comp_head = comp(key, &self->data[head]); \ 240 | int comp_tail = comp(key, &self->data[tail]); \ 241 | if (comp_head < 0 || comp_tail > 0) \ 242 | return Length; \ 243 | if (comp_head == 0) \ 244 | return head; \ 245 | if (comp_tail == 0) \ 246 | return tail; \ 247 | \ 248 | middle = (tail - head) / 2; \ 249 | int comp_mid = comp(key, &self->data[middle]); \ 250 | if (comp_mid == 0) \ 251 | return middle; \ 252 | else if (0 < comp_mid) \ 253 | --tail, head = middle; \ 254 | else \ 255 | ++head, tail = middle; \ 256 | } \ 257 | } \ 258 | \ 259 | TypeName##_iterator TypeName##_bfind_by(const TypeName *self, const T *key, TypeName##_Compare comp) \ 260 | { \ 261 | int index = TypeName##_bsearch(self, key, comp); \ 262 | if (0 <= index && index < Length) \ 263 | return new_##TypeName##_iterator((T *)&self->data[index]); \ 264 | return self->end((TypeName *)&self); \ 265 | } \ 266 | \ 267 | size_t TypeName##_indexof(const TypeName *self, const T key) \ 268 | { \ 269 | for (int i = 0; i < Length; ++i) \ 270 | if (self->data[i] == key) \ 271 | return i; \ 272 | return Length; \ 273 | } \ 274 | \ 275 | size_t TypeName##_indexof_by(const TypeName *self, TypeName##_Find comp) \ 276 | { \ 277 | for (int i = 0; i < Length; ++i) \ 278 | if (comp(&self->data[i])) \ 279 | return i; \ 280 | return Length; \ 281 | } \ 282 | \ 283 | size_t TypeName##_bindexof(const TypeName *self, const T key) \ 284 | { \ 285 | T *p = (T*)bsearch(&key, self->data, Length, sizeof(T), TypeName##_comparer); \ 286 | if (self->data <= p && p <= &(self->data[Length - 1])) \ 287 | return p - self->data; \ 288 | return Length; \ 289 | } \ 290 | \ 291 | size_t TypeName##_bindexof_by(const TypeName *self, const T *key, TypeName##_Compare comp) \ 292 | { \ 293 | int index = TypeName##_bsearch(self, key, comp); \ 294 | if (0 <= index && index < Length) \ 295 | return index; \ 296 | return Length; \ 297 | } \ 298 | \ 299 | bool TypeName##_contains(const TypeName *self, const T key) \ 300 | { \ 301 | for (int i = 0; i < Length; ++i) \ 302 | if (self->data[i] == key) \ 303 | return 1; \ 304 | return 0; \ 305 | } \ 306 | \ 307 | bool TypeName##_contains_by(const TypeName *self, TypeName##_Find comp) \ 308 | { \ 309 | for (int i = 0; i < Length; ++i) \ 310 | if (comp(&self->data[i])) \ 311 | return 1; \ 312 | return 0; \ 313 | } \ 314 | \ 315 | bool TypeName##_bcontains(const TypeName *self, const T key) \ 316 | { \ 317 | T *p = (T*)bsearch(&key, self->data, Length, sizeof(T), TypeName##_comparer); \ 318 | if (self->data <= p && p <= &(self->data[Length - 1])) \ 319 | return 1; \ 320 | return 0; \ 321 | } \ 322 | \ 323 | bool TypeName##_bcontains_by(const TypeName *self, const T *key, TypeName##_Compare comp) \ 324 | { \ 325 | int index = TypeName##_bsearch(self, key, comp); \ 326 | if (0 <= index && index < Length) \ 327 | return 1; \ 328 | return 0; \ 329 | } \ 330 | \ 331 | void TypeName##_for_each(const TypeName *self, void (*f)(const T)) \ 332 | { \ 333 | for (int i = 0; i < Length; ++i) \ 334 | f(self->data[i]); \ 335 | } \ 336 | \ 337 | void TypeName##_for_each_ptr(TypeName *self, void (*f)(T *)) \ 338 | { \ 339 | for (int i = 0; i < Length; ++i) \ 340 | f(&self->data[i]); \ 341 | } \ 342 | \ 343 | void TypeName##_for_each_cptr(const TypeName *self, void (*f)(const T *)) \ 344 | { \ 345 | for (int i = 0; i < Length; ++i) \ 346 | f(&self->data[i]); \ 347 | } \ 348 | \ 349 | TypeName new_##TypeName(void) \ 350 | { \ 351 | static TypeName temp = \ 352 | { \ 353 | .size = TypeName##_size, \ 354 | .get = TypeName##_get, \ 355 | .get_ptr = TypeName##_get_ptr, \ 356 | .get_cptr = TypeName##_get_cptr, \ 357 | .clone = TypeName##_clone, \ 358 | .begin = TypeName##_begin, \ 359 | .end = TypeName##_end, \ 360 | .find = TypeName##_find, \ 361 | .find_by = TypeName##_find_by, \ 362 | .indexof = TypeName##_indexof, \ 363 | .indexof_by = TypeName##_indexof_by, \ 364 | .contains = TypeName##_contains, \ 365 | .contains_by = TypeName##_contains_by, \ 366 | .bfind = TypeName##_bfind, \ 367 | .bfind_by = TypeName##_bfind_by, \ 368 | .bindexof = TypeName##_bindexof, \ 369 | .bindexof_by = TypeName##_bindexof_by, \ 370 | .bcontains = TypeName##_bcontains, \ 371 | .bcontains_by = TypeName##_bcontains_by, \ 372 | .fill = TypeName##_fill, \ 373 | .fill_ptr = TypeName##_fill_ptr, \ 374 | .sort = TypeName##_sort, \ 375 | .sort_by = TypeName##_sort_by, \ 376 | .for_each = TypeName##_for_each, \ 377 | .for_each_ptr = TypeName##_for_each_ptr, \ 378 | .for_each_cptr = TypeName##_for_each_cptr}; \ 379 | return temp; \ 380 | } \ 381 | \ 382 | void TypeName##_iterator_next(TypeName##_iterator *self) \ 383 | { \ 384 | ++(self->ptr); \ 385 | } \ 386 | \ 387 | void TypeName##_iterator_prev(TypeName##_iterator *self) \ 388 | { \ 389 | --(self->ptr); \ 390 | } \ 391 | \ 392 | T TypeName##_iterator_get(const TypeName##_iterator *self) \ 393 | { \ 394 | return *(self->ptr); \ 395 | } \ 396 | \ 397 | T *TypeName##_iterator_get_ptr(TypeName##_iterator *self) \ 398 | { \ 399 | return self->ptr; \ 400 | } \ 401 | \ 402 | bool TypeName##_iterator_equals(const TypeName##_iterator *self, const TypeName##_iterator *other) \ 403 | { \ 404 | return self->ptr == other->ptr; \ 405 | } \ 406 | \ 407 | TypeName##_iterator new_##TypeName##_iterator(T *p) \ 408 | { \ 409 | TypeName##_iterator it = { \ 410 | .ptr = p, \ 411 | .next = TypeName##_iterator_next, \ 412 | .prev = TypeName##_iterator_prev, \ 413 | .get = TypeName##_iterator_get, \ 414 | .get_ptr = TypeName##_iterator_get_ptr, \ 415 | .equals = TypeName##_iterator_equals \ 416 | }; \ 417 | \ 418 | return it; \ 419 | } 420 | 421 | #endif -------------------------------------------------------------------------------- /include/darray.h: -------------------------------------------------------------------------------- 1 | #ifndef C_STL_DARRAY_H 2 | #define C_STL_DARRAY_H 3 | 4 | #include 5 | #include 6 | 7 | //매크로로 확장되는, 배열 유사템플릿입니다. 8 | //정적배열의 래퍼 유사클래스 선언을 생성합니다. 9 | #define decl_darray(declname, type) \ 10 | \ 11 | /*배열 유사클래스 전방선언*/ \ 12 | struct declname; \ 13 | typedef struct declname declname; \ 14 | \ 15 | /*전용 반복자 유사클래스 전방선언*/ \ 16 | struct declname##_iterator; \ 17 | typedef struct declname##_iterator declname##_iterator; \ 18 | \ 19 | /*반복자 유사클래스.*/ \ 20 | struct declname##_iterator \ 21 | { \ 22 | type *ptr; \ 23 | \ 24 | /*반복을 하거나 역반복을 수행*/ \ 25 | void (*next)(declname##_iterator *); \ 26 | void (*prev)(declname##_iterator *); \ 27 | \ 28 | /*반복자에 담긴 값이나 그 포인터를 가져옴.*/ \ 29 | type (*get)(const declname##_iterator *); \ 30 | type *(*get_ptr)(declname##_iterator *); \ 31 | \ 32 | /*두 반복자를 비교. 같으면 true*/ \ 33 | bool (*equals)(const declname##_iterator *, const declname##_iterator *); \ 34 | }; \ 35 | /*유사 메서드 선언*/ \ 36 | void declname##_iterator_next(declname##_iterator *); \ 37 | void declname##_iterator_prev(declname##_iterator *); \ 38 | type declname##_iterator_get(const declname##_iterator *); \ 39 | type *declname##_iterator_get_ptr(declname##_iterator *); \ 40 | bool declname##_iterator_equals(const declname##_iterator *, const declname##_iterator *); \ 41 | /*비멤버 new 함수 선언*/ \ 42 | declname##_iterator new_##declname##_iterator(type *); \ 43 | \ 44 | /*실체화되는 배열 유사클래스*/ \ 45 | struct declname \ 46 | { \ 47 | type *const data; \ 48 | const size_t length; \ 49 | \ 50 | void (*clear)(declname *); \ 51 | void (*realloc)(declname *, size_t); \ 52 | \ 53 | bool (*is_empty)(const declname *); \ 54 | bool (*is_not_empty)(const declname *); \ 55 | \ 56 | /*길이를 가져옴*/ \ 57 | size_t (*size)(const declname *); \ 58 | \ 59 | /*요소 액세스*/ \ 60 | type (*get)(const declname *, size_t); \ 61 | type *(*get_ptr)(declname *, size_t); \ 62 | const type *(*get_cptr)(const declname *, size_t); \ 63 | \ 64 | declname (*clone)(const declname *); \ 65 | \ 66 | /*반복자를 반환*/ \ 67 | declname##_iterator (*begin)(declname *); \ 68 | declname##_iterator (*end)(declname *); \ 69 | \ 70 | /*선형탐색 후 찾은 위치의 반복자를 반환*/ \ 71 | declname##_iterator (*find)(const declname *, const type); \ 72 | declname##_iterator (*find_by)(const declname *, int (*)(const type *)); \ 73 | \ 74 | /*선형탐색 후 해당하는 인덱스를 반환*/ \ 75 | size_t (*indexof)(const declname *, const type); \ 76 | size_t (*indexof_by)(const declname *, int (*)(const type *)); \ 77 | \ 78 | /*선형탐색으로 포함 여부를 확인*/ \ 79 | bool (*contains)(const declname *, const type); \ 80 | bool (*contains_by)(const declname *, int (*)(const type *)); \ 81 | \ 82 | /*이진탐색 후 찾은 위치의 반복자를 반환*/ \ 83 | declname##_iterator (*bfind)(const declname *, const type); \ 84 | declname##_iterator (*bfind_by)(const declname *, const type *, int (*)(const type *, const type *)); \ 85 | \ 86 | /*이진탐색 후 해당하는 인덱스를 반환*/ \ 87 | size_t (*bindexof)(const declname *, const type); \ 88 | size_t (*bindexof_by)(const declname *, const type *, int (*)(const type *, const type *)); \ 89 | \ 90 | /*이진탐색으로 포함 여부를 확인*/ \ 91 | bool (*bcontains)(const declname *, const type); \ 92 | bool (*bcontains_by)(const declname *, const type *, int (*)(const type *, const type *)); \ 93 | \ 94 | /*해당 값이나 값의 포인터로, 배열을 채움*/ \ 95 | void (*fill)(declname *, const type); \ 96 | void (*fill_ptr)(declname *, const type *); \ 97 | \ 98 | /*정렬용*/ \ 99 | void (*sort)(declname *); \ 100 | void (*sort_by)(declname *, int (*)(const type *, const type *)); \ 101 | \ 102 | /*콜백함수를 받아서 범위기반 루프를 돎*/ \ 103 | void (*for_each)(const declname *, void (*)(const type)); \ 104 | void (*for_each_ptr)(declname *, void (*)(type *)); \ 105 | void (*for_each_cptr)(const declname *, void (*)(const type *)); \ 106 | }; \ 107 | /*유사 메서드 선언*/ \ 108 | void declname##_clear(declname *); \ 109 | void declname##_realloc(declname *, size_t); \ 110 | bool declname##_is_empty(const declname *); \ 111 | bool declname##_is_not_empty(const declname *); \ 112 | size_t declname##_size(const declname *); \ 113 | type declname##_get(const declname *, size_t); \ 114 | type *declname##_get_ptr(declname *, size_t); \ 115 | const type *declname##_get_cptr(const declname *, size_t); \ 116 | declname declname##_clone(const declname *); \ 117 | declname##_iterator declname##_begin(declname *); \ 118 | declname##_iterator declname##_end(declname *); \ 119 | declname##_iterator declname##_find(const declname *, const type); \ 120 | declname##_iterator declname##_find_by(const declname *, int (*)(const type *)); \ 121 | size_t declname##_indexof(const declname *, const type); \ 122 | size_t declname##_indexof_by(const declname *, int (*)(const type *)); \ 123 | bool declname##_contains(const declname *, const type); \ 124 | bool declname##_contains_by(const declname *, int (*)(const type *)); \ 125 | declname##_iterator declname##_bfind(const declname *, const type); \ 126 | declname##_iterator declname##_bfind_by(const declname *, const type *, int (*)(const type *, const type *)); \ 127 | size_t declname##_bindexof(const declname *, const type); \ 128 | size_t declname##_bindexof_by(const declname *, const type *, int (*)(const type *, const type *)); \ 129 | bool declname##_bcontains(const declname *, const type); \ 130 | bool declname##_bcontains_by(const declname *, const type *, int (*)(const type *, const type *)); \ 131 | void declname##_fill(declname *, const type); \ 132 | void declname##_fill_ptr(declname *, const type *); \ 133 | void declname##_sort(declname *); \ 134 | void declname##_sort_by(declname *, int (*)(const type *, const type *)); \ 135 | void declname##_for_each(const declname *, void (*)(const type)); \ 136 | void declname##_for_each_ptr(declname *, void (*)(type *)); \ 137 | void declname##_for_each_cptr(const declname *, void (*)(const type *)); \ 138 | \ 139 | /*비멤버 함수*/ \ 140 | declname new_##declname(); \ 141 | declname new_##declname##_with(size_t); 142 | 143 | //정적배열의 래퍼 유사클래스 구현을 생성합니다. 144 | #define def_darray(declname, type) \ 145 | \ 146 | /*배열 메서드 정의.*/ \ 147 | void declname##_clear(declname *self) \ 148 | { \ 149 | free((type *)self->data); \ 150 | *(const type **)(&self->data) = NULL; \ 151 | *(size_t *)(&self->length) = 0; \ 152 | } \ 153 | \ 154 | void declname##_realloc(declname *self, size_t len) \ 155 | { \ 156 | realloc((type *)self->data, sizeof(type) * len); \ 157 | *(size_t *)(&self->length) = len; \ 158 | } \ 159 | \ 160 | bool declname##_is_empty(const declname *self) \ 161 | { \ 162 | return self->data == NULL; \ 163 | } \ 164 | \ 165 | bool declname##_is_not_empty(const declname *self) \ 166 | { \ 167 | return self->data != NULL; \ 168 | } \ 169 | \ 170 | size_t declname##_size(const declname *self) \ 171 | { \ 172 | return self->length; \ 173 | } \ 174 | type declname##_get(const declname *self, size_t index) \ 175 | { \ 176 | return self->data[index]; \ 177 | } \ 178 | type *declname##_get_ptr(declname *self, size_t index) \ 179 | { \ 180 | return (type *)&(self->data[index]); \ 181 | } \ 182 | const type *declname##_get_cptr(const declname *self, size_t index) \ 183 | { \ 184 | return &(self->data[index]); \ 185 | } \ 186 | \ 187 | int declname##_comparer(const void *lhs, const void *rhs) \ 188 | { \ 189 | return *(type *)lhs - *(type *)rhs; \ 190 | } \ 191 | \ 192 | void declname##_sort(declname *self) \ 193 | { \ 194 | qsort(self->data, self->length, sizeof(type), declname##_comparer); \ 195 | } \ 196 | \ 197 | void declname##_sort_by(declname *self, int (*comp)(const type *, const type *)) \ 198 | { \ 199 | qsort(self->data, self->length, sizeof(type), (int (*)(const void *, const void *))comp); \ 200 | } \ 201 | \ 202 | declname declname##_clone(const declname *self) \ 203 | { \ 204 | declname temp = new_##declname##_with(self->length); \ 205 | for (int i = 0; i < self->length; ++i) \ 206 | temp.data[i] = self->data[i]; \ 207 | return temp; \ 208 | } \ 209 | \ 210 | declname##_iterator declname##_begin(declname *self) \ 211 | { \ 212 | return new_##declname##_iterator(self->data); \ 213 | } \ 214 | \ 215 | declname##_iterator declname##_end(declname *self) \ 216 | { \ 217 | return new_##declname##_iterator(self->data + self->length); \ 218 | } \ 219 | \ 220 | void declname##_fill(declname *self, const type value) \ 221 | { \ 222 | for (int i = 0; i < self->length; ++i) \ 223 | self->data[i] = value; \ 224 | } \ 225 | \ 226 | void declname##_fill_ptr(declname *self, const type *value) \ 227 | { \ 228 | for (int i = 0; i < self->length; ++i) \ 229 | self->data[i] = *value; \ 230 | } \ 231 | \ 232 | declname##_iterator declname##_find(const declname *self, const type key) \ 233 | { \ 234 | for (int i = 0; i < self->length; ++i) \ 235 | if (self->data[i] == key) \ 236 | return new_##declname##_iterator((type *)&(self->data[i])); \ 237 | \ 238 | return self->end((declname *)&self); \ 239 | } \ 240 | \ 241 | declname##_iterator declname##_find_by(const declname *self, int (*comp)(const type *)) \ 242 | { \ 243 | for (int i = 0; i < self->length; ++i) \ 244 | if (comp(&self->data[i])) \ 245 | return new_##declname##_iterator((type *)&(self->data[i])); \ 246 | \ 247 | return self->end((declname *)&self); \ 248 | } \ 249 | \ 250 | declname##_iterator declname##_bfind(const declname *self, const type key) \ 251 | { \ 252 | type *p = bsearch(&key, self->data, self->length, sizeof(type), declname##_comparer); \ 253 | if (self->data <= p && p <= &(self->data[self->length - 1])) \ 254 | return new_##declname##_iterator(p); \ 255 | return self->end((declname *)&self); \ 256 | } \ 257 | \ 258 | int declname##_bsearch(const declname *self, const type *key, int (*comp)(const type *, const type *)) \ 259 | { \ 260 | int head = 0; \ 261 | int tail = self->length - 1; \ 262 | int middle; \ 263 | \ 264 | while (1) \ 265 | { \ 266 | int comp_head = comp(key, &self->data[head]); \ 267 | int comp_tail = comp(key, &self->data[tail]); \ 268 | if (comp_head < 0 || comp_tail > 0) \ 269 | return self->length; \ 270 | if (comp_head == 0) \ 271 | return head; \ 272 | if (comp_tail == 0) \ 273 | return tail; \ 274 | \ 275 | middle = (tail - head) / 2; \ 276 | int comp_mid = comp(key, &self->data[middle]); \ 277 | if (comp_mid == 0) \ 278 | return middle; \ 279 | else if (0 < comp_mid) /*key가 중간치보다 큼*/ \ 280 | --tail, head = middle; \ 281 | else /*key가 중간치보다 작음*/ \ 282 | ++head, tail = middle; \ 283 | } \ 284 | } \ 285 | \ 286 | declname##_iterator declname##_bfind_by(const declname *self, const type *key, int (*comp)(const type *, const type *)) \ 287 | { \ 288 | int index = declname##_bsearch(self, key, comp); \ 289 | if (0 <= index && index < self->length) \ 290 | return new_##declname##_iterator((type *)&self->data[index]); \ 291 | return self->end((declname *)&self); \ 292 | } \ 293 | \ 294 | size_t declname##_indexof(const declname *self, const type key) \ 295 | { \ 296 | for (int i = 0; i < self->length; ++i) \ 297 | if (self->data[i] == key) \ 298 | return i; \ 299 | return self->length; \ 300 | } \ 301 | \ 302 | size_t declname##_indexof_by(const declname *self, int (*comp)(const type *)) \ 303 | { \ 304 | for (int i = 0; i < self->length; ++i) \ 305 | if (comp(&self->data[i])) \ 306 | return i; \ 307 | return self->length; \ 308 | } \ 309 | \ 310 | size_t declname##_bindexof(const declname *self, const type key) \ 311 | { \ 312 | type *p = bsearch(&key, self->data, self->length, sizeof(type), declname##_comparer); \ 313 | if (self->data <= p && p <= &(self->data[self->length - 1])) \ 314 | return p - self->data; \ 315 | return self->length; \ 316 | } \ 317 | \ 318 | size_t declname##_bindexof_by(const declname *self, const type *key, int (*comp)(const type *, const type *)) \ 319 | { \ 320 | int index = declname##_bsearch(self, key, comp); \ 321 | if (0 <= index && index < self->length) \ 322 | return index; \ 323 | return self->length; \ 324 | } \ 325 | \ 326 | bool declname##_contains(const declname *self, const type key) \ 327 | { \ 328 | for (int i = 0; i < self->length; ++i) \ 329 | if (self->data[i] == key) \ 330 | return 1; \ 331 | return 0; \ 332 | } \ 333 | \ 334 | bool declname##_contains_by(const declname *self, int (*comp)(const type *)) \ 335 | { \ 336 | for (int i = 0; i < self->length; ++i) \ 337 | if (comp(&self->data[i])) \ 338 | return 1; \ 339 | return 0; \ 340 | } \ 341 | \ 342 | bool declname##_bcontains(const declname *self, const type key) \ 343 | { \ 344 | type *p = bsearch(&key, self->data, self->length, sizeof(type), declname##_comparer); \ 345 | if (self->data <= p && p <= &(self->data[self->length - 1])) \ 346 | return 1; \ 347 | return 0; \ 348 | } \ 349 | \ 350 | bool declname##_bcontains_by(const declname *self, const type *key, int (*comp)(const type *, const type *)) \ 351 | { \ 352 | int index = declname##_bsearch(self, key, comp); \ 353 | if (0 <= index && index < self->length) \ 354 | return 1; \ 355 | return 0; \ 356 | } \ 357 | \ 358 | void declname##_for_each(const declname *self, void (*f)(const type)) \ 359 | { \ 360 | for (int i = 0; i < self->length; ++i) \ 361 | f(self->data[i]); \ 362 | } \ 363 | \ 364 | void declname##_for_each_ptr(declname *self, void (*f)(type *)) \ 365 | { \ 366 | for (int i = 0; i < self->length; ++i) \ 367 | f(&self->data[i]); \ 368 | } \ 369 | \ 370 | void declname##_for_each_cptr(const declname *self, void (*f)(const type *)) \ 371 | { \ 372 | for (int i = 0; i < self->length; ++i) \ 373 | f(&self->data[i]); \ 374 | } \ 375 | \ 376 | declname new_##declname() \ 377 | { \ 378 | declname temp = \ 379 | { \ 380 | .data = NULL, \ 381 | .length = 0, \ 382 | .clear = declname##_clear, \ 383 | .realloc = declname##_realloc, \ 384 | .is_empty = declname##_is_empty, \ 385 | .is_not_empty = declname##_is_not_empty, \ 386 | .size = declname##_size, \ 387 | .get = declname##_get, \ 388 | .get_ptr = declname##_get_ptr, \ 389 | .get_cptr = declname##_get_cptr, \ 390 | .sort = declname##_sort, \ 391 | .sort_by = declname##_sort_by, \ 392 | .clone = declname##_clone, \ 393 | .begin = declname##_begin, \ 394 | .end = declname##_end, \ 395 | .fill = declname##_fill, \ 396 | .fill_ptr = declname##_fill_ptr, \ 397 | .find = declname##_find, \ 398 | .find_by = declname##_find_by, \ 399 | .bfind = declname##_bfind, \ 400 | .bfind_by = declname##_bfind_by, \ 401 | .indexof = declname##_indexof, \ 402 | .indexof_by = declname##_indexof_by, \ 403 | .bindexof = declname##_bindexof, \ 404 | .bindexof_by = declname##_bindexof_by, \ 405 | .contains = declname##_contains, \ 406 | .contains_by = declname##_contains_by, \ 407 | .bcontains = declname##_bcontains, \ 408 | .bcontains_by = declname##_bcontains_by, \ 409 | .for_each = declname##_for_each, \ 410 | .for_each_ptr = declname##_for_each_ptr, \ 411 | .for_each_cptr = declname##_for_each_cptr}; \ 412 | return temp; \ 413 | } \ 414 | \ 415 | declname new_##declname##_with(size_t len) \ 416 | { \ 417 | declname temp = \ 418 | { \ 419 | .data = malloc(sizeof(type) * len), \ 420 | .length = len, \ 421 | .clear = declname##_clear, \ 422 | .realloc = declname##_realloc, \ 423 | .is_empty = declname##_is_empty, \ 424 | .is_not_empty = declname##_is_not_empty, \ 425 | .size = declname##_size, \ 426 | .get = declname##_get, \ 427 | .get_ptr = declname##_get_ptr, \ 428 | .get_cptr = declname##_get_cptr, \ 429 | .sort = declname##_sort, \ 430 | .sort_by = declname##_sort_by, \ 431 | .clone = declname##_clone, \ 432 | .begin = declname##_begin, \ 433 | .end = declname##_end, \ 434 | .fill = declname##_fill, \ 435 | .fill_ptr = declname##_fill_ptr, \ 436 | .find = declname##_find, \ 437 | .find_by = declname##_find_by, \ 438 | .bfind = declname##_bfind, \ 439 | .bfind_by = declname##_bfind_by, \ 440 | .indexof = declname##_indexof, \ 441 | .indexof_by = declname##_indexof_by, \ 442 | .bindexof = declname##_bindexof, \ 443 | .bindexof_by = declname##_bindexof_by, \ 444 | .contains = declname##_contains, \ 445 | .contains_by = declname##_contains_by, \ 446 | .bcontains = declname##_bcontains, \ 447 | .bcontains_by = declname##_bcontains_by, \ 448 | .for_each = declname##_for_each, \ 449 | .for_each_ptr = declname##_for_each_ptr, \ 450 | .for_each_cptr = declname##_for_each_cptr}; \ 451 | return temp; \ 452 | } \ 453 | \ 454 | /*반복자 메서드 정의*/ \ 455 | void declname##_iterator_next(declname##_iterator *self) \ 456 | { \ 457 | ++(self->ptr); \ 458 | } \ 459 | \ 460 | void declname##_iterator_prev(declname##_iterator *self) \ 461 | { \ 462 | --(self->ptr); \ 463 | } \ 464 | \ 465 | type declname##_iterator_get(const declname##_iterator *self) \ 466 | { \ 467 | return *(self->ptr); \ 468 | } \ 469 | \ 470 | type *declname##_iterator_get_ptr(declname##_iterator *self) \ 471 | { \ 472 | return self->ptr; \ 473 | } \ 474 | \ 475 | bool declname##_iterator_equals(const declname##_iterator *self, const declname##_iterator *other) \ 476 | { \ 477 | return self->ptr == other->ptr; \ 478 | } \ 479 | \ 480 | declname##_iterator new_##declname##_iterator(type *p) \ 481 | { \ 482 | declname##_iterator it = \ 483 | { \ 484 | p, \ 485 | declname##_iterator_next, \ 486 | declname##_iterator_prev, \ 487 | declname##_iterator_get, \ 488 | declname##_iterator_get_ptr, \ 489 | declname##_iterator_equals}; \ 490 | return it; \ 491 | } 492 | 493 | #endif 494 | --------------------------------------------------------------------------------