0.1.0をリリース。
@@ -0,0 +1,52 @@ | ||
1 | +CSTL | |
2 | +==== | |
3 | + | |
4 | + CSTLは、C++のSTLライクなC/C++用のコンテナライブラリです。vector, deque, | |
5 | + list, set, multiset, map, multimap, stringを提供します。 | |
6 | + | |
7 | + | |
8 | +SourceForge.jp CSTL | |
9 | + http://sourceforge.jp/projects/cstl/ | |
10 | + | |
11 | + | |
12 | +ディレクトリ・ファイル構成 | |
13 | + cstl/ | |
14 | + vector.h vector | |
15 | + deque.h deque | |
16 | + list.h list | |
17 | + rbtree.h 赤黒木(set/mapのデータ構造) | |
18 | + set.h set | |
19 | + map.h map | |
20 | + string.h string | |
21 | + doc/ | |
22 | + CSTL.rd CSTLのドキュメント(RDファイル) | |
23 | + CSTL.html CSTL.rdをhtml化したもの | |
24 | + Makefile CSTL.htmlを生成するためのMakefile | |
25 | + test/ 単体テスト | |
26 | + sample/ CSTLを使用したサンプル | |
27 | + heap.h 独自アロケータのヘッダ | |
28 | + heap.c 独自アロケータのソース | |
29 | + README.txt このファイル | |
30 | + | |
31 | + | |
32 | +インストール | |
33 | + CSTL.htmlをご覧下さい。 | |
34 | + | |
35 | + | |
36 | +独自アロケータについて | |
37 | + stdlib.hが使えない環境でmalloc/realloc/freeの代わりに使用することができます。 | |
38 | + 詳しくはheap.hの使用例をご覧下さい。 | |
39 | + | |
40 | + | |
41 | +単体テストについて | |
42 | + gcc3.4.4で動作確認をしています。(stringのみstd::stringを使用してテストしてい | |
43 | + るのでg++を使用) makeを実行すればビルドからテスト実行までを行います。 | |
44 | + | |
45 | + | |
46 | +ドキュメント生成について | |
47 | + CSTL.rdからhtml等を生成するにはrubyとRDtoolのインストールが必要です。docディ | |
48 | + レクトリでmakeを実行すればCSTL.htmlが生成されます。 | |
49 | + | |
50 | + | |
51 | + | |
52 | +vim:set ts=8 sts=2 sw=2 tw=78 et ft=memo: |
@@ -0,0 +1,193 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2006, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file rbtree_debug.h | |
27 | + * \brief set/mapデバッグ用 | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2006-11-14 | |
30 | + * | |
31 | + * 赤黒木の表示とベリファイ | |
32 | + */ | |
33 | +#ifndef CSTL_RBTREE_DEBUG_H_INCLUDED | |
34 | +#define CSTL_RBTREE_DEBUG_H_INCLUDED | |
35 | + | |
36 | +#include <stdio.h> | |
37 | +#include <limits.h> | |
38 | + | |
39 | +enum { | |
40 | + VERBOSE = 0, | |
41 | + VISUAL | |
42 | +}; | |
43 | + | |
44 | +#define RBTREE_DEBUG_IMPLEMENT(Name, KeyType, ValueType, Compare, Order, format1, format2, map, value, visual) \ | |
45 | +\ | |
46 | +static size_t Name##_max_depth;\ | |
47 | +static size_t Name##_min_depth;\ | |
48 | +\ | |
49 | +static char *Name##_str_color(RBTreeColor c)\ | |
50 | +{\ | |
51 | + char *r = "(r)";\ | |
52 | + char *b = "(b)";\ | |
53 | + if (c == RBTREE_RED) {\ | |
54 | + return r;\ | |
55 | + } else if (c == RBTREE_BLACK) {\ | |
56 | + return b;\ | |
57 | + } else {\ | |
58 | + assert(0);\ | |
59 | + return 0;\ | |
60 | + }\ | |
61 | +}\ | |
62 | +\ | |
63 | +static void Name##_p(Name##RBTreeNode *self, size_t depth)\ | |
64 | +{\ | |
65 | + size_t i;\ | |
66 | + if (visual) {\ | |
67 | + for (i = 0; i < depth; i++) {\ | |
68 | + printf(" ");\ | |
69 | + }\ | |
70 | + if (map) {\ | |
71 | + printf("%s["#format1"]["#format2"]", Name##_str_color(self->color), self->key, self->value);\ | |
72 | + } else {\ | |
73 | + printf("%s["#format1"]", Name##_str_color(self->color), self->key);\ | |
74 | + }\ | |
75 | + } else {\ | |
76 | + if (map) {\ | |
77 | + printf("n[%p], p[%p], l[%p], r[%p], k["#format1"], v["#format2"], c[%s], d[%d]",\ | |
78 | + self, self->parent, self->left, self->right, self->key, self->value,\ | |
79 | + Name##_str_color(self->color), depth);\ | |
80 | + } else {\ | |
81 | + printf("n[%p], p[%p], l[%p], r[%p], v["#format1"], c[%s], d[%d]",\ | |
82 | + self, self->parent, self->left, self->right, self->key,\ | |
83 | + Name##_str_color(self->color), depth);\ | |
84 | + }\ | |
85 | + if (Name##RBTreeNode_is_root(self)) {\ | |
86 | + printf(", root");\ | |
87 | + } else if (Name##RBTreeNode_is_nil(self->left) && Name##RBTreeNode_is_nil(self->right)) {\ | |
88 | + printf(", leaf");\ | |
89 | + }\ | |
90 | + }\ | |
91 | + printf("\n");\ | |
92 | +}\ | |
93 | +\ | |
94 | +static void Name##Node_print(Name##RBTreeNode *self)\ | |
95 | +{\ | |
96 | + static size_t depth = 0;\ | |
97 | + if (Name##RBTreeNode_is_nil(self)) {\ | |
98 | + return;\ | |
99 | + }\ | |
100 | + depth++;\ | |
101 | + if (Name##_max_depth < depth) Name##_max_depth = depth;\ | |
102 | + if (Name##RBTreeNode_is_nil(self->right) && Name##RBTreeNode_is_nil(self->left)) {\ | |
103 | + if (Name##_min_depth > depth) Name##_min_depth = depth;\ | |
104 | + }\ | |
105 | + if (visual) {\ | |
106 | + Name##Node_print(self->right);\ | |
107 | + Name##_p(self, depth);\ | |
108 | + Name##Node_print(self->left);\ | |
109 | + } else {\ | |
110 | + Name##_p(self, depth);\ | |
111 | + Name##Node_print(self->left);\ | |
112 | + Name##Node_print(self->right);\ | |
113 | + }\ | |
114 | + depth--;\ | |
115 | +}\ | |
116 | +\ | |
117 | +void Name##_print(Name *self)\ | |
118 | +{\ | |
119 | + Name##RBTreeNode *root;\ | |
120 | + assert(Name##RBTreeNode_is_head(self->tree));\ | |
121 | + root = Name##RBTree_get_root(self->tree);\ | |
122 | + Name##_max_depth = 0;\ | |
123 | + Name##_min_depth = UINT_MAX;\ | |
124 | + Name##Node_print(root);\ | |
125 | + printf("min depth[%d], max depth[%d]\n", Name##_min_depth, Name##_max_depth);\ | |
126 | + printf("\n");\ | |
127 | +}\ | |
128 | +\ | |
129 | +static size_t Name##RBTreeNode_black_count(Name##RBTreeNode *t, Name##RBTreeNode *root)\ | |
130 | +{\ | |
131 | + size_t count;\ | |
132 | + if (Name##RBTreeNode_is_nil(t)) {\ | |
133 | + return 0;\ | |
134 | + }\ | |
135 | + count = t->color == RBTREE_BLACK ? 1 : 0;\ | |
136 | + if (t == root) {\ | |
137 | + return count;\ | |
138 | + } else {\ | |
139 | + return count + Name##RBTreeNode_black_count(t->parent, root);\ | |
140 | + }\ | |
141 | +}\ | |
142 | +\ | |
143 | +int Name##_verify(Name *self)\ | |
144 | +{\ | |
145 | + size_t len;\ | |
146 | + Name##RBTreeNode *l;\ | |
147 | + Name##RBTreeNode *r;\ | |
148 | + Name##Iterator pos;\ | |
149 | + Name##RBTree *tree = self->tree;\ | |
150 | + if (Name##RBTree_empty(tree) || Name##RBTree_begin(tree) == Name##RBTree_end(tree)) {\ | |
151 | + return Name##RBTree_empty(tree) && Name##RBTree_begin(tree) == Name##RBTree_end(tree) &&\ | |
152 | + tree->left == &Name##RBTree_nil && tree->right == &Name##RBTree_nil && tree->parent == &Name##RBTree_nil;\ | |
153 | + }\ | |
154 | + len = Name##RBTreeNode_black_count(Name##RBTree_begin(tree), Name##RBTree_get_root(tree));\ | |
155 | + for (pos = Name##RBTree_begin(tree); pos != Name##RBTree_end(tree); pos = Name##RBTree_next(pos)) {\ | |
156 | + l = pos->left;\ | |
157 | + r = pos->right;\ | |
158 | + if (pos->color == RBTREE_RED) {\ | |
159 | + if ((!Name##RBTreeNode_is_nil(l) && l->color == RBTREE_RED) ||\ | |
160 | + (!Name##RBTreeNode_is_nil(r) && r->color == RBTREE_RED)) {\ | |
161 | + return 0;\ | |
162 | + }\ | |
163 | + }\ | |
164 | + if (!Name##RBTreeNode_is_nil(l) && Name##RBTree_cmp(pos->key, l->key, Order) < 0) {\ | |
165 | + return 0;\ | |
166 | + }\ | |
167 | + if (!Name##RBTreeNode_is_nil(r) && Name##RBTree_cmp(r->key, pos->key, Order) < 0) {\ | |
168 | + return 0;\ | |
169 | + }\ | |
170 | + if (Name##RBTreeNode_is_nil(l) && Name##RBTreeNode_is_nil(r) &&\ | |
171 | + Name##RBTreeNode_black_count(pos, Name##RBTree_get_root(tree)) != len) {\ | |
172 | + return 0;\ | |
173 | + }\ | |
174 | + }\ | |
175 | + return 1;\ | |
176 | +}\ | |
177 | +\ | |
178 | + | |
179 | +#define SET_DEBUG_INTERFACE(Name) \ | |
180 | +void Name##_print(Name *self);\ | |
181 | +int Name##_verify(Name *self);\ | |
182 | + | |
183 | +#define MAP_DEBUG_INTERFACE(Name) \ | |
184 | +void Name##_print(Name *self);\ | |
185 | +int Name##_verify(Name *self);\ | |
186 | + | |
187 | +#define SET_DEBUG_IMPLEMENT(Name, Type, Compare, Order, format, visual) \ | |
188 | +RBTREE_DEBUG_IMPLEMENT(Name, Type, Type, Compare, Order, format, format, 0, key, visual) \ | |
189 | + | |
190 | +#define MAP_DEBUG_IMPLEMENT(Name, KeyType, ValueType, Compare, Order, format1, format2, visual) \ | |
191 | +RBTREE_DEBUG_IMPLEMENT(Name, KeyType, ValueType, Compare, Order, format1, format2, 1, value, visual) \ | |
192 | + | |
193 | +#endif /* CSTL_RBTREE_DEBUG_H_INCLUDED */ |
@@ -0,0 +1,545 @@ | ||
1 | +#include "test.h" | |
2 | + | |
3 | + | |
4 | +VECTOR_IMPLEMENT(UCharVector, unsigned char) | |
5 | +VECTOR_IMPLEMENT(IntVector, int) | |
6 | + | |
7 | +static UCharVector *uv; | |
8 | +static IntVector *iv; | |
9 | + | |
10 | +#define SIZE (VECTOR_INIT_SIZE-1) | |
11 | + | |
12 | + | |
13 | +static unsigned char hoge[256]; | |
14 | +static int piyo[256]; | |
15 | + | |
16 | +void vector_init_hoge(void) | |
17 | +{ | |
18 | + int i; | |
19 | + for (i = 0; i < 256; i++) { | |
20 | + hoge[i] = i; | |
21 | + } | |
22 | +} | |
23 | + | |
24 | +void vector_init_piyo(void) | |
25 | +{ | |
26 | + int i; | |
27 | + for (i = 0; i < 256; i++) { | |
28 | + piyo[i] = i; | |
29 | + } | |
30 | +} | |
31 | + | |
32 | + | |
33 | +void VectorTest_test_1_1(void) | |
34 | +{ | |
35 | + size_t a; | |
36 | + printf("***** test_1_1 *****\n"); | |
37 | + uv = UCharVector_new(); | |
38 | + vector_init_hoge(); | |
39 | + /* 初期状態 */ | |
40 | + assert(UCharVector_capacity(uv) == SIZE); | |
41 | + assert(UCharVector_size(uv) == 0); | |
42 | + assert(UCharVector_empty(uv)); | |
43 | + /* assign */ | |
44 | + assert(UCharVector_assign(uv, hoge, SIZE)); | |
45 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
46 | + assert(UCharVector_capacity(uv) == SIZE); | |
47 | + assert(UCharVector_size(uv) == SIZE); | |
48 | + assert(!UCharVector_empty(uv)); | |
49 | + /* clear */ | |
50 | + UCharVector_clear(uv); | |
51 | + assert(UCharVector_size(uv) == 0); | |
52 | + assert(UCharVector_empty(uv)); | |
53 | + /* assign */ | |
54 | + assert(UCharVector_assign(uv, &hoge[1], 255)); | |
55 | + assert(memcmp(UCharVector_at(uv, 0), &hoge[1], 255) == 0); | |
56 | + a = UCharVector_capacity(uv); | |
57 | + assert(a > SIZE); | |
58 | + assert(UCharVector_size(uv) == 255); | |
59 | + assert(!UCharVector_empty(uv)); | |
60 | + /* clear */ | |
61 | + UCharVector_clear(uv); | |
62 | + assert(UCharVector_size(uv) == 0); | |
63 | + assert(UCharVector_empty(uv)); | |
64 | + /* assign */ | |
65 | + assert(UCharVector_assign(uv, hoge, SIZE)); | |
66 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
67 | + assert(UCharVector_capacity(uv) == a); | |
68 | + assert(UCharVector_size(uv) == SIZE); | |
69 | + assert(!UCharVector_empty(uv)); | |
70 | + /* clear */ | |
71 | + UCharVector_clear(uv); | |
72 | + assert(UCharVector_size(uv) == 0); | |
73 | + assert(UCharVector_empty(uv)); | |
74 | + /* reserve */ | |
75 | + assert(UCharVector_reserve(uv, 1024)); | |
76 | + assert(UCharVector_capacity(uv) == 1024); | |
77 | + assert(UCharVector_size(uv) == 0); | |
78 | + assert(UCharVector_empty(uv)); | |
79 | + | |
80 | + assert(UCharVector_reserve(uv, 256)); | |
81 | + assert(UCharVector_capacity(uv) == 1024); | |
82 | + assert(UCharVector_size(uv) == 0); | |
83 | + assert(UCharVector_empty(uv)); | |
84 | + | |
85 | + UCharVector_delete(uv); | |
86 | +} | |
87 | + | |
88 | +void VectorTest_test_1_2(void) | |
89 | +{ | |
90 | + int i; | |
91 | + size_t a; | |
92 | + printf("***** test_1_2 *****\n"); | |
93 | + uv = UCharVector_new(); | |
94 | + vector_init_hoge(); | |
95 | + /* push_back */ | |
96 | + for (i = 0; i < SIZE; i++) { | |
97 | + assert(UCharVector_push_back(uv, hoge[i])); | |
98 | + assert(UCharVector_size(uv) == i+1); | |
99 | + assert(UCharVector_front(uv) == hoge[0]); | |
100 | + assert(UCharVector_back(uv) == hoge[i]); | |
101 | + } | |
102 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
103 | + assert(UCharVector_capacity(uv) == SIZE); | |
104 | + assert(UCharVector_size(uv) == SIZE); | |
105 | + assert(!UCharVector_empty(uv)); | |
106 | + for (i = i; i < 256; i++) { | |
107 | + assert(UCharVector_push_back(uv, hoge[i])); | |
108 | + assert(UCharVector_size(uv) == i+1); | |
109 | + assert(UCharVector_front(uv) == hoge[0]); | |
110 | + assert(UCharVector_back(uv) == hoge[i]); | |
111 | + } | |
112 | + assert(memcmp(UCharVector_at(uv, 0), hoge, 256) == 0); | |
113 | + a = UCharVector_capacity(uv); | |
114 | + assert(a > SIZE); | |
115 | + assert(UCharVector_size(uv) == 256); | |
116 | + assert(!UCharVector_empty(uv)); | |
117 | + /* front, back */ | |
118 | + assert(UCharVector_front(uv) == hoge[0]); | |
119 | + assert(UCharVector_back(uv) == hoge[255]); | |
120 | + /* pop_back */ | |
121 | + for (i = 255; i >= 0; i--) { | |
122 | + assert(UCharVector_front(uv) == hoge[0]); | |
123 | + assert(UCharVector_back(uv) == hoge[i]); | |
124 | + assert(UCharVector_pop_back(uv) == hoge[i]); | |
125 | + assert(UCharVector_size(uv) == i); | |
126 | + } | |
127 | + assert(UCharVector_size(uv) == 0); | |
128 | + assert(UCharVector_empty(uv)); | |
129 | + assert(UCharVector_capacity(uv) == a); | |
130 | + | |
131 | + UCharVector_delete(uv); | |
132 | +} | |
133 | + | |
134 | +void VectorTest_test_1_3(void) | |
135 | +{ | |
136 | + int i; | |
137 | + printf("***** test_1_3 *****\n"); | |
138 | + uv = UCharVector_new(); | |
139 | + vector_init_hoge(); | |
140 | + /* assign */ | |
141 | + assert(UCharVector_assign(uv, hoge, SIZE)); | |
142 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
143 | + assert(UCharVector_capacity(uv) == SIZE); | |
144 | + assert(UCharVector_size(uv) == SIZE); | |
145 | + assert(!UCharVector_empty(uv)); | |
146 | + /* at */ | |
147 | + for (i = 0; i < SIZE; i++) { | |
148 | + assert(*UCharVector_at(uv, i) == hoge[i]); | |
149 | + *UCharVector_at(uv, i) = hoge[i]+1; | |
150 | + assert(*UCharVector_at(uv, i) == hoge[i]+1); | |
151 | + } | |
152 | + assert(UCharVector_capacity(uv) == SIZE); | |
153 | + assert(UCharVector_size(uv) == SIZE); | |
154 | + assert(!UCharVector_empty(uv)); | |
155 | + | |
156 | + UCharVector_delete(uv); | |
157 | +} | |
158 | + | |
159 | +void VectorTest_test_1_4(void) | |
160 | +{ | |
161 | + int i; | |
162 | + unsigned char buf[256]; | |
163 | + printf("***** test_1_4 *****\n"); | |
164 | + uv = UCharVector_new(); | |
165 | + /* insert */ | |
166 | + for (i = 0; i < SIZE; i++) { | |
167 | + assert(UCharVector_insert(uv, 0, hoge[i])); | |
168 | + buf[i] = SIZE - i - 1; | |
169 | + } | |
170 | + assert(memcmp(UCharVector_at(uv, 0), buf, SIZE) == 0); | |
171 | + assert(UCharVector_capacity(uv) == SIZE); | |
172 | + assert(UCharVector_size(uv) == SIZE); | |
173 | + assert(!UCharVector_empty(uv)); | |
174 | + for (i = SIZE; i < 256; i++) { | |
175 | + assert(UCharVector_insert(uv, UCharVector_size(uv), hoge[i])); | |
176 | + buf[i] = i; | |
177 | + assert(UCharVector_capacity(uv) > SIZE); | |
178 | + } | |
179 | + assert(memcmp(&UCharVector_at(uv, 0)[SIZE], &buf[SIZE], 256-SIZE) == 0); | |
180 | + assert(UCharVector_size(uv) == 256); | |
181 | + assert(UCharVector_insert(uv, SIZE, 0)); | |
182 | + assert(memcmp(UCharVector_at(uv, 0), buf, SIZE) == 0); | |
183 | + assert(UCharVector_at(uv, 0)[SIZE] == 0); | |
184 | + assert(memcmp(&UCharVector_at(uv, 0)[SIZE+1], &buf[SIZE], 256-SIZE) == 0); | |
185 | + assert(UCharVector_size(uv) == 257); | |
186 | + /* erase */ | |
187 | + UCharVector_erase(uv, SIZE); | |
188 | + assert(memcmp(UCharVector_at(uv, 0), buf, SIZE) == 0); | |
189 | + assert(memcmp(&UCharVector_at(uv, 0)[SIZE], &buf[SIZE], 256-SIZE) == 0); | |
190 | + for (i = SIZE; i < 256; i++) { | |
191 | + UCharVector_erase(uv, UCharVector_size(uv)-1); | |
192 | + } | |
193 | + assert(memcmp(UCharVector_at(uv, 0), buf, SIZE) == 0); | |
194 | + assert(UCharVector_size(uv) == SIZE); | |
195 | + for (i = 0; i < SIZE; i++) { | |
196 | + assert(memcmp(UCharVector_at(uv, 0), &buf[i], SIZE-i) == 0); | |
197 | + UCharVector_erase(uv, 0); | |
198 | + assert(UCharVector_size(uv) == SIZE-i-1); | |
199 | + } | |
200 | + assert(UCharVector_size(uv) == 0); | |
201 | + | |
202 | + UCharVector_delete(uv); | |
203 | +} | |
204 | + | |
205 | +void VectorTest_test_1_5(void) | |
206 | +{ | |
207 | + printf("***** test_1_5 *****\n"); | |
208 | + uv = UCharVector_new(); | |
209 | + vector_init_hoge(); | |
210 | + /* insert_n */ | |
211 | + assert(UCharVector_insert_n(uv, 0, hoge, SIZE)); | |
212 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
213 | + assert(UCharVector_capacity(uv) == SIZE); | |
214 | + assert(UCharVector_size(uv) == SIZE); | |
215 | + | |
216 | + assert(UCharVector_insert_n(uv, UCharVector_size(uv), &hoge[SIZE], 256-SIZE)); | |
217 | + assert(memcmp(UCharVector_at(uv, 0), hoge, 256) == 0); | |
218 | + assert(UCharVector_capacity(uv) > SIZE); | |
219 | + assert(UCharVector_size(uv) == 256); | |
220 | + | |
221 | + assert(UCharVector_insert_n(uv, SIZE, hoge, SIZE)); | |
222 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
223 | + assert(memcmp(&UCharVector_at(uv, 0)[SIZE], hoge, 256) == 0); | |
224 | + assert(UCharVector_size(uv) == 256+SIZE); | |
225 | + | |
226 | + assert(UCharVector_insert_n(uv, 0, hoge, 1)); | |
227 | + assert(*UCharVector_at(uv, 0) == hoge[0]); | |
228 | + assert(memcmp(&UCharVector_at(uv, 0)[1], hoge, SIZE) == 0); | |
229 | + assert(memcmp(&UCharVector_at(uv, 0)[SIZE+1], hoge, 256) == 0); | |
230 | + assert(UCharVector_size(uv) == 257+SIZE); | |
231 | + /* erase_n */ | |
232 | + UCharVector_erase_n(uv, 0, 1); | |
233 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
234 | + assert(memcmp(&UCharVector_at(uv, 0)[SIZE], hoge, 256) == 0); | |
235 | + assert(UCharVector_size(uv) == 256+SIZE); | |
236 | + | |
237 | + UCharVector_erase_n(uv, SIZE, SIZE); | |
238 | + assert(memcmp(UCharVector_at(uv, 0), hoge, 256) == 0); | |
239 | + assert(UCharVector_size(uv) == 256); | |
240 | + | |
241 | + UCharVector_erase_n(uv, SIZE, 256-SIZE); | |
242 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
243 | + assert(UCharVector_size(uv) == SIZE); | |
244 | + | |
245 | + UCharVector_erase_n(uv, 0, SIZE); | |
246 | + assert(UCharVector_size(uv) == 0); | |
247 | + | |
248 | + UCharVector_delete(uv); | |
249 | +} | |
250 | + | |
251 | +void VectorTest_test_1_6(void) | |
252 | +{ | |
253 | + UCharVector *x; | |
254 | + size_t i; | |
255 | + printf("***** test_1_6 *****\n"); | |
256 | + uv = UCharVector_new(); | |
257 | + vector_init_hoge(); | |
258 | + | |
259 | + assert(UCharVector_assign(uv, hoge, SIZE)); | |
260 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
261 | + assert(UCharVector_size(uv) == SIZE); | |
262 | + assert(UCharVector_capacity(uv) == SIZE); | |
263 | + /* resize */ | |
264 | + assert(UCharVector_resize(uv, SIZE + 10, 255)); | |
265 | + assert(UCharVector_size(uv) == SIZE + 10); | |
266 | + assert(memcmp(UCharVector_at(uv, 0), hoge, SIZE) == 0); | |
267 | + assert(*UCharVector_at(uv, SIZE) == 255); | |
268 | + assert(*UCharVector_at(uv, SIZE + 9) == 255); | |
269 | + assert(UCharVector_capacity(uv) > SIZE); | |
270 | + | |
271 | + assert(UCharVector_resize(uv, SIZE - 10, 255)); | |
272 | + assert(UCharVector_size(uv) == SIZE - 10); | |
273 | + | |
274 | + assert(UCharVector_resize(uv, 0, 255)); | |
275 | + assert(UCharVector_empty(uv)); | |
276 | + /* shrink */ | |
277 | + assert(UCharVector_resize(uv, 1000, 255)); | |
278 | + assert(UCharVector_capacity(uv) == 1000); | |
279 | + assert(UCharVector_size(uv) == 1000); | |
280 | + assert(UCharVector_resize(uv, 100, 255)); | |
281 | + assert(UCharVector_capacity(uv) == 1000); | |
282 | + assert(UCharVector_size(uv) == 100); | |
283 | + UCharVector_shrink(uv, 500); | |
284 | + assert(UCharVector_capacity(uv) == 500); | |
285 | + assert(UCharVector_size(uv) == 100); | |
286 | + UCharVector_shrink(uv, 0); | |
287 | + assert(UCharVector_capacity(uv) == 100); | |
288 | + assert(UCharVector_size(uv) == 100); | |
289 | + assert(UCharVector_resize(uv, 10, 255)); | |
290 | + UCharVector_shrink(uv, 500); | |
291 | + assert(UCharVector_capacity(uv) == 100); | |
292 | + assert(UCharVector_size(uv) == 10); | |
293 | + UCharVector_shrink(uv, 0); | |
294 | + assert(UCharVector_capacity(uv) == 10); | |
295 | + assert(UCharVector_size(uv) == 10); | |
296 | + /* new_copy */ | |
297 | + x = UCharVector_new_copy(uv); | |
298 | + assert(UCharVector_capacity(x) == 10); | |
299 | + assert(UCharVector_size(x) == 10); | |
300 | + for (i = 0; i < UCharVector_size(uv); i++) { | |
301 | + assert(*UCharVector_at(x, i) == *UCharVector_at(uv, i)); | |
302 | + } | |
303 | + | |
304 | + UCharVector_delete(uv); | |
305 | + UCharVector_delete(x); | |
306 | +} | |
307 | + | |
308 | + | |
309 | +void VectorTest_test_2_1(void) | |
310 | +{ | |
311 | + size_t a; | |
312 | + printf("***** test_2_1 *****\n"); | |
313 | + iv = IntVector_new(); | |
314 | + vector_init_piyo(); | |
315 | + /* 初期状態 */ | |
316 | + assert(IntVector_capacity(iv) == SIZE); | |
317 | + assert(IntVector_size(iv) == 0); | |
318 | + assert(IntVector_empty(iv)); | |
319 | + /* assign */ | |
320 | + assert(IntVector_assign(iv, piyo, SIZE)); | |
321 | + assert(memcmp(IntVector_at(iv, 0), piyo, SIZE) == 0); | |
322 | + assert(IntVector_capacity(iv) == SIZE); | |
323 | + assert(IntVector_size(iv) == SIZE); | |
324 | + assert(!IntVector_empty(iv)); | |
325 | + /* clear */ | |
326 | + IntVector_clear(iv); | |
327 | + assert(IntVector_size(iv) == 0); | |
328 | + assert(IntVector_empty(iv)); | |
329 | + /* assign */ | |
330 | + assert(IntVector_assign(iv, &piyo[1], 255)); | |
331 | + assert(memcmp(IntVector_at(iv, 0), &piyo[1], 255) == 0); | |
332 | + a = IntVector_capacity(iv); | |
333 | + assert(a > SIZE); | |
334 | + assert(IntVector_size(iv) == 255); | |
335 | + assert(!IntVector_empty(iv)); | |
336 | + /* clear */ | |
337 | + IntVector_clear(iv); | |
338 | + assert(IntVector_size(iv) == 0); | |
339 | + assert(IntVector_empty(iv)); | |
340 | + /* assign */ | |
341 | + assert(IntVector_assign(iv, piyo, SIZE)); | |
342 | + assert(memcmp(IntVector_at(iv, 0), piyo, SIZE) == 0); | |
343 | + assert(IntVector_capacity(iv) == a); | |
344 | + assert(IntVector_size(iv) == SIZE); | |
345 | + assert(!IntVector_empty(iv)); | |
346 | + /* clear */ | |
347 | + IntVector_clear(iv); | |
348 | + assert(IntVector_size(iv) == 0); | |
349 | + assert(IntVector_empty(iv)); | |
350 | + /* reserve */ | |
351 | + assert(IntVector_reserve(iv, 1024)); | |
352 | + assert(IntVector_capacity(iv) == 1024); | |
353 | + assert(IntVector_size(iv) == 0); | |
354 | + assert(IntVector_empty(iv)); | |
355 | + | |
356 | + assert(IntVector_reserve(iv, 256)); | |
357 | + assert(IntVector_capacity(iv) == 1024); | |
358 | + assert(IntVector_size(iv) == 0); | |
359 | + assert(IntVector_empty(iv)); | |
360 | + | |
361 | + IntVector_delete(iv); | |
362 | +} | |
363 | + | |
364 | +void VectorTest_test_2_2(void) | |
365 | +{ | |
366 | + int i; | |
367 | + size_t a; | |
368 | + printf("***** test_2_2 *****\n"); | |
369 | + iv = IntVector_new(); | |
370 | + vector_init_piyo(); | |
371 | + /* push_back */ | |
372 | + for (i = 0; i < SIZE; i++) { | |
373 | + assert(IntVector_push_back(iv, piyo[i])); | |
374 | + assert(IntVector_size(iv) == i+1); | |
375 | + assert(IntVector_front(iv) == piyo[0]); | |
376 | + assert(IntVector_back(iv) == piyo[i]); | |
377 | + } | |
378 | + assert(memcmp(IntVector_at(iv, 0), piyo, SIZE) == 0); | |
379 | + assert(IntVector_capacity(iv) == SIZE); | |
380 | + assert(IntVector_size(iv) == SIZE); | |
381 | + assert(!IntVector_empty(iv)); | |
382 | + for (i = i; i < 256; i++) { | |
383 | + assert(IntVector_push_back(iv, piyo[i])); | |
384 | + assert(IntVector_size(iv) == i+1); | |
385 | + assert(IntVector_front(iv) == piyo[0]); | |
386 | + assert(IntVector_back(iv) == piyo[i]); | |
387 | + } | |
388 | + assert(memcmp(IntVector_at(iv, 0), piyo, 256) == 0); | |
389 | + a = IntVector_capacity(iv); | |
390 | + assert(a > SIZE); | |
391 | + assert(IntVector_size(iv) == 256); | |
392 | + assert(!IntVector_empty(iv)); | |
393 | + /* front, back */ | |
394 | + assert(IntVector_front(iv) == piyo[0]); | |
395 | + assert(IntVector_back(iv) == piyo[255]); | |
396 | + /* pop_back */ | |
397 | + for (i = 255; i >= 0; i--) { | |
398 | + assert(IntVector_front(iv) == piyo[0]); | |
399 | + assert(IntVector_back(iv) == piyo[i]); | |
400 | + assert(IntVector_pop_back(iv) == piyo[i]); | |
401 | + assert(IntVector_size(iv) == i); | |
402 | + } | |
403 | + assert(IntVector_size(iv) == 0); | |
404 | + assert(IntVector_empty(iv)); | |
405 | + assert(IntVector_capacity(iv) == a); | |
406 | + | |
407 | + IntVector_delete(iv); | |
408 | +} | |
409 | + | |
410 | +void VectorTest_test_2_3(void) | |
411 | +{ | |
412 | + int i; | |
413 | + printf("***** test_2_3 *****\n"); | |
414 | + iv = IntVector_new(); | |
415 | + vector_init_piyo(); | |
416 | + /* assign */ | |
417 | + assert(IntVector_assign(iv, piyo, SIZE)); | |
418 | + assert(memcmp(IntVector_at(iv, 0), piyo, SIZE) == 0); | |
419 | + assert(IntVector_capacity(iv) == SIZE); | |
420 | + assert(IntVector_size(iv) == SIZE); | |
421 | + assert(!IntVector_empty(iv)); | |
422 | + /* at */ | |
423 | + for (i = 0; i < SIZE; i++) { | |
424 | + assert(*IntVector_at(iv, i) == piyo[i]); | |
425 | + *IntVector_at(iv, i) = piyo[i]+1; | |
426 | + assert(*IntVector_at(iv, i) == piyo[i]+1); | |
427 | + } | |
428 | + assert(IntVector_capacity(iv) == SIZE); | |
429 | + assert(IntVector_size(iv) == SIZE); | |
430 | + assert(!IntVector_empty(iv)); | |
431 | + | |
432 | + IntVector_delete(iv); | |
433 | +} | |
434 | + | |
435 | +void VectorTest_test_2_4(void) | |
436 | +{ | |
437 | + int i; | |
438 | + int buf[256]; | |
439 | + printf("***** test_2_4 *****\n"); | |
440 | + iv = IntVector_new(); | |
441 | + /* insert */ | |
442 | + for (i = 0; i < SIZE; i++) { | |
443 | + assert(IntVector_insert(iv, 0, piyo[i])); | |
444 | + buf[i] = SIZE - i - 1; | |
445 | + } | |
446 | + assert(memcmp(IntVector_at(iv, 0), buf, SIZE) == 0); | |
447 | + assert(IntVector_capacity(iv) == SIZE); | |
448 | + assert(IntVector_size(iv) == SIZE); | |
449 | + assert(!IntVector_empty(iv)); | |
450 | + for (i = SIZE; i < 256; i++) { | |
451 | + assert(IntVector_insert(iv, IntVector_size(iv), piyo[i])); | |
452 | + buf[i] = i; | |
453 | + assert(IntVector_capacity(iv) > SIZE); | |
454 | + } | |
455 | + assert(memcmp(&IntVector_at(iv, 0)[SIZE], &buf[SIZE], 256-SIZE) == 0); | |
456 | + assert(IntVector_size(iv) == 256); | |
457 | + assert(IntVector_insert(iv, SIZE, 0)); | |
458 | + assert(memcmp(IntVector_at(iv, 0), buf, SIZE) == 0); | |
459 | + assert(IntVector_at(iv, 0)[SIZE] == 0); | |
460 | + assert(memcmp(&IntVector_at(iv, 0)[SIZE+1], &buf[SIZE], 256-SIZE) == 0); | |
461 | + assert(IntVector_size(iv) == 257); | |
462 | + /* erase */ | |
463 | + IntVector_erase(iv, SIZE); | |
464 | + assert(memcmp(IntVector_at(iv, 0), buf, SIZE) == 0); | |
465 | + assert(memcmp(&IntVector_at(iv, 0)[SIZE], &buf[SIZE], 256-SIZE) == 0); | |
466 | + for (i = SIZE; i < 256; i++) { | |
467 | + IntVector_erase(iv, IntVector_size(iv)-1); | |
468 | + } | |
469 | + assert(memcmp(IntVector_at(iv, 0), buf, SIZE) == 0); | |
470 | + assert(IntVector_size(iv) == SIZE); | |
471 | + for (i = 0; i < SIZE; i++) { | |
472 | + assert(memcmp(IntVector_at(iv, 0), &buf[i], SIZE-i) == 0); | |
473 | + IntVector_erase(iv, 0); | |
474 | + assert(IntVector_size(iv) == SIZE-i-1); | |
475 | + } | |
476 | + assert(IntVector_size(iv) == 0); | |
477 | + | |
478 | + IntVector_delete(iv); | |
479 | +} | |
480 | + | |
481 | +void VectorTest_test_2_5(void) | |
482 | +{ | |
483 | + printf("***** test_2_5 *****\n"); | |
484 | + iv = IntVector_new(); | |
485 | + vector_init_piyo(); | |
486 | + /* insert_n */ | |
487 | + assert(IntVector_insert_n(iv, 0, piyo, SIZE)); | |
488 | + assert(memcmp(IntVector_at(iv, 0), piyo, SIZE) == 0); | |
489 | + assert(IntVector_capacity(iv) == SIZE); | |
490 | + assert(IntVector_size(iv) == SIZE); | |
491 | + | |
492 | + assert(IntVector_insert_n(iv, IntVector_size(iv), &piyo[SIZE], 256-SIZE)); | |
493 | + assert(memcmp(IntVector_at(iv, 0), piyo, 256) == 0); | |
494 | + assert(IntVector_capacity(iv) > SIZE); | |
495 | + assert(IntVector_size(iv) == 256); | |
496 | + | |
497 | + assert(IntVector_insert_n(iv, SIZE, piyo, SIZE)); | |
498 | + assert(memcmp(IntVector_at(iv, 0), piyo, SIZE) == 0); | |
499 | + assert(memcmp(&IntVector_at(iv, 0)[SIZE], piyo, 256) == 0); | |
500 | + assert(IntVector_size(iv) == 256+SIZE); | |
501 | + | |
502 | + assert(IntVector_insert_n(iv, 0, piyo, 1)); | |
503 | + assert(*IntVector_at(iv, 0) == piyo[0]); | |
504 | + assert(memcmp(&IntVector_at(iv, 0)[1], piyo, SIZE) == 0); | |
505 | + assert(memcmp(&IntVector_at(iv, 0)[SIZE+1], piyo, 256) == 0); | |
506 | + assert(IntVector_size(iv) == 257+SIZE); | |
507 | + /* erase_n */ | |
508 | + IntVector_erase_n(iv, 0, 1); | |
509 | + assert(memcmp(IntVector_at(iv, 0), piyo, SIZE) == 0); | |
510 | + assert(memcmp(&IntVector_at(iv, 0)[SIZE], piyo, 256) == 0); | |
511 | + assert(IntVector_size(iv) == 256+SIZE); | |
512 | + | |
513 | + IntVector_erase_n(iv, SIZE, SIZE); | |
514 | + assert(memcmp(IntVector_at(iv, 0), piyo, 256) == 0); | |
515 | + assert(IntVector_size(iv) == 256); | |
516 | + | |
517 | + IntVector_erase_n(iv, SIZE, 256-SIZE); | |
518 | + assert(memcmp(IntVector_at(iv, 0), piyo, SIZE) == 0); | |
519 | + assert(IntVector_size(iv) == SIZE); | |
520 | + | |
521 | + IntVector_erase_n(iv, 0, SIZE); | |
522 | + assert(IntVector_size(iv) == 0); | |
523 | + | |
524 | + IntVector_delete(iv); | |
525 | +} | |
526 | + | |
527 | + | |
528 | + | |
529 | + | |
530 | +void VectorTest_run(void) | |
531 | +{ | |
532 | + printf("\n===== vector test =====\n"); | |
533 | + VectorTest_test_1_1(); | |
534 | + VectorTest_test_1_2(); | |
535 | + VectorTest_test_1_3(); | |
536 | + VectorTest_test_1_4(); | |
537 | + VectorTest_test_1_5(); | |
538 | + VectorTest_test_1_6(); | |
539 | + VectorTest_test_2_1(); | |
540 | + VectorTest_test_2_2(); | |
541 | + VectorTest_test_2_3(); | |
542 | + VectorTest_test_2_4(); | |
543 | + VectorTest_test_2_5(); | |
544 | +} | |
545 | + |
@@ -0,0 +1,925 @@ | ||
1 | +#include "test.h" | |
2 | + | |
3 | + | |
4 | + | |
5 | +DEQUE_IMPLEMENT(UCharDeque, unsigned char) | |
6 | +DEQUE_IMPLEMENT(IntDeque, int) | |
7 | + | |
8 | +static UCharDeque *ud; | |
9 | +static IntDeque *id; | |
10 | + | |
11 | +#define MAX 255 | |
12 | + | |
13 | +static unsigned char hoge[MAX]; | |
14 | +static int piyo[MAX]; | |
15 | + | |
16 | +void deque_init_hoge(void) | |
17 | +{ | |
18 | + int i; | |
19 | + for (i = 0; i < MAX; i++) { | |
20 | + hoge[i] = i; | |
21 | + } | |
22 | +} | |
23 | + | |
24 | +void deque_init_piyo(void) | |
25 | +{ | |
26 | + int i; | |
27 | + for (i = 0; i < MAX; i++) { | |
28 | + piyo[i] = i; | |
29 | + } | |
30 | +} | |
31 | + | |
32 | +int ud_cmp(size_t idx, unsigned char *buf, size_t n) | |
33 | +{ | |
34 | + int i, j; | |
35 | + for (i = idx, j = 0; i < idx + n; i++, j++) { | |
36 | +/* printf("%d, %d\n", *UCharDeque_at(ud, i), buf[j]);*/ | |
37 | + if (*UCharDeque_at(ud, i) != buf[j]) return 1; | |
38 | + } | |
39 | + return 0; | |
40 | +} | |
41 | + | |
42 | +int id_cmp(size_t idx, int *buf, size_t n) | |
43 | +{ | |
44 | + int i, j; | |
45 | + for (i = idx, j = 0; i < idx + n; i++, j++) { | |
46 | +/* printf("%d, %d\n", *IntDeque_at(id, i), buf[j]);*/ | |
47 | + if (*IntDeque_at(id, i) != buf[j]) return 1; | |
48 | + } | |
49 | + return 0; | |
50 | +} | |
51 | + | |
52 | + | |
53 | +void DequeTest_test_1_1(void) | |
54 | +{ | |
55 | + int i, j; | |
56 | + printf("***** test_1_1 *****\n"); | |
57 | + ud = UCharDeque_new(MAX); | |
58 | + /* 初期状態 */ | |
59 | + assert(UCharDeque_max_size(ud) == MAX); | |
60 | + assert(UCharDeque_size(ud) == 0); | |
61 | + assert(UCharDeque_empty(ud)); | |
62 | + assert(!UCharDeque_full(ud)); | |
63 | + for (j = 0; j < MAX+1; j++) { | |
64 | + ud->begin = ud->end = j; | |
65 | + assert(UCharDeque_size(ud) == 0); | |
66 | + /* assign */ | |
67 | + assert(UCharDeque_assign(ud, hoge, MAX)); | |
68 | + assert(ud_cmp(0, hoge, MAX) == 0); | |
69 | + assert(UCharDeque_size(ud) == MAX); | |
70 | + assert(!UCharDeque_empty(ud)); | |
71 | + assert(UCharDeque_full(ud)); | |
72 | + /* at */ | |
73 | + for (i = 0; i < UCharDeque_size(ud); i++) { | |
74 | + assert(*UCharDeque_at(ud, i) == hoge[i]); | |
75 | + *UCharDeque_at(ud, i) = hoge[MAX - i -1]; | |
76 | + assert(*UCharDeque_at(ud, i) == hoge[MAX - i -1]); | |
77 | + } | |
78 | + /* clear */ | |
79 | + UCharDeque_clear(ud); | |
80 | + assert(UCharDeque_size(ud) == 0); | |
81 | + assert(UCharDeque_empty(ud)); | |
82 | + assert(!UCharDeque_full(ud)); | |
83 | + /* assign */ | |
84 | + assert(UCharDeque_assign(ud, hoge, MAX/2)); | |
85 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
86 | + assert(UCharDeque_size(ud) == MAX/2); | |
87 | + assert(!UCharDeque_empty(ud)); | |
88 | + assert(!UCharDeque_full(ud)); | |
89 | + /* MAX以上で失敗 */ | |
90 | + assert(!UCharDeque_assign(ud, hoge, MAX+1)); | |
91 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
92 | + assert(UCharDeque_size(ud) == MAX/2); | |
93 | + assert(!UCharDeque_empty(ud)); | |
94 | + assert(!UCharDeque_full(ud)); | |
95 | + /* clear */ | |
96 | + UCharDeque_clear(ud); | |
97 | + assert(UCharDeque_size(ud) == 0); | |
98 | + } | |
99 | + | |
100 | + UCharDeque_delete(ud); | |
101 | +} | |
102 | + | |
103 | +void DequeTest_test_1_2(void) | |
104 | +{ | |
105 | + int i, j; | |
106 | + size_t size; | |
107 | + printf("***** test_1_2 *****\n"); | |
108 | + ud = UCharDeque_new(MAX); | |
109 | + for (j = 0; j < MAX+1; j++) { | |
110 | + ud->begin = ud->end = j; | |
111 | + assert(UCharDeque_size(ud) == 0); | |
112 | + /* push_back */ | |
113 | + /* MAXまで */ | |
114 | + for (i = 0; i < MAX; i++) { | |
115 | + size = UCharDeque_size(ud); | |
116 | + assert(UCharDeque_push_back(ud, hoge[i])); | |
117 | + assert(UCharDeque_size(ud) == size + 1); | |
118 | + } | |
119 | + assert(ud_cmp(0, hoge, MAX) == 0); | |
120 | + assert(UCharDeque_size(ud) == MAX); | |
121 | + assert(!UCharDeque_empty(ud)); | |
122 | + assert(UCharDeque_full(ud)); | |
123 | + /* FULLで失敗 */ | |
124 | + assert(!UCharDeque_push_back(ud, hoge[0])); | |
125 | + assert(UCharDeque_size(ud) == MAX); | |
126 | + assert(!UCharDeque_empty(ud)); | |
127 | + assert(UCharDeque_full(ud)); | |
128 | + /* front */ | |
129 | + assert(UCharDeque_front(ud) == hoge[0]); | |
130 | + /* back */ | |
131 | + assert(UCharDeque_back(ud) == hoge[MAX-1]); | |
132 | + /* pop_front */ | |
133 | + size = UCharDeque_size(ud); | |
134 | + assert(UCharDeque_pop_front(ud) == hoge[0]); | |
135 | + assert(UCharDeque_size(ud) == size - 1); | |
136 | + /* push_back */ | |
137 | + size = UCharDeque_size(ud); | |
138 | + assert(UCharDeque_push_back(ud, hoge[0])); | |
139 | + assert(UCharDeque_size(ud) == size + 1); | |
140 | + assert(ud_cmp(0, &hoge[1], MAX-1) == 0); | |
141 | + assert(ud_cmp(MAX-1, hoge, 1) == 0); | |
142 | + assert(UCharDeque_size(ud) == MAX); | |
143 | + assert(!UCharDeque_empty(ud)); | |
144 | + assert(UCharDeque_full(ud)); | |
145 | + /* pop_front */ | |
146 | + for (i = 0; i < MAX; i++) { | |
147 | + size = UCharDeque_size(ud); | |
148 | + if (i < MAX-1) { | |
149 | + assert(UCharDeque_pop_front(ud) == hoge[i+1]); | |
150 | + } else { | |
151 | + assert(UCharDeque_pop_front(ud) == hoge[0]); | |
152 | + } | |
153 | + assert(UCharDeque_size(ud) == size - 1); | |
154 | + } | |
155 | + assert(UCharDeque_size(ud) == 0); | |
156 | + assert(UCharDeque_empty(ud)); | |
157 | + assert(!UCharDeque_full(ud)); | |
158 | + } | |
159 | + | |
160 | + UCharDeque_delete(ud); | |
161 | +} | |
162 | + | |
163 | +void DequeTest_test_1_3(void) | |
164 | +{ | |
165 | + int i, j; | |
166 | + size_t size; | |
167 | + printf("***** test_1_3 *****\n"); | |
168 | + ud = UCharDeque_new(MAX); | |
169 | + for (j = 0; j < MAX+1; j++) { | |
170 | + ud->begin = ud->end = j; | |
171 | + assert(UCharDeque_size(ud) == 0); | |
172 | + /* push_front */ | |
173 | + /* MAXまで */ | |
174 | + for (i = 0; i < MAX; i++) { | |
175 | + size = UCharDeque_size(ud); | |
176 | + assert(UCharDeque_push_front(ud, hoge[MAX-i-1])); | |
177 | + assert(UCharDeque_size(ud) == size + 1); | |
178 | + } | |
179 | + assert(ud_cmp(0, hoge, MAX) == 0); | |
180 | + assert(UCharDeque_size(ud) == MAX); | |
181 | + assert(!UCharDeque_empty(ud)); | |
182 | + assert(UCharDeque_full(ud)); | |
183 | + /* FULLで失敗 */ | |
184 | + assert(!UCharDeque_push_front(ud, hoge[0])); | |
185 | + assert(UCharDeque_size(ud) == MAX); | |
186 | + assert(!UCharDeque_empty(ud)); | |
187 | + assert(UCharDeque_full(ud)); | |
188 | + /* front */ | |
189 | + assert(UCharDeque_front(ud) == hoge[0]); | |
190 | + /* back */ | |
191 | + assert(UCharDeque_back(ud) == hoge[MAX-1]); | |
192 | + /* pop_back */ | |
193 | + size = UCharDeque_size(ud); | |
194 | + assert(UCharDeque_pop_back(ud) == hoge[MAX-1]); | |
195 | + assert(UCharDeque_pop_back(ud) == hoge[MAX-2]); | |
196 | + assert(UCharDeque_size(ud) == size - 2); | |
197 | + /* push_front */ | |
198 | + size = UCharDeque_size(ud); | |
199 | + assert(UCharDeque_push_front(ud, hoge[MAX-1])); | |
200 | + assert(UCharDeque_push_front(ud, hoge[MAX-2])); | |
201 | + assert(UCharDeque_size(ud) == size + 2); | |
202 | + assert(ud_cmp(0, &hoge[MAX-2], 2) == 0); | |
203 | + assert(ud_cmp(2, hoge, MAX-2) == 0); | |
204 | + assert(UCharDeque_size(ud) == MAX); | |
205 | + assert(!UCharDeque_empty(ud)); | |
206 | + assert(UCharDeque_full(ud)); | |
207 | + /* pop_back */ | |
208 | + for (i = MAX-3; i >= 0; i--) { | |
209 | + size = UCharDeque_size(ud); | |
210 | + assert(UCharDeque_pop_back(ud) == hoge[i]); | |
211 | + assert(UCharDeque_size(ud) == size - 1); | |
212 | + } | |
213 | + assert(UCharDeque_pop_back(ud) == hoge[MAX-1]); | |
214 | + assert(UCharDeque_pop_back(ud) == hoge[MAX-2]); | |
215 | + | |
216 | + assert(UCharDeque_size(ud) == 0); | |
217 | + assert(UCharDeque_empty(ud)); | |
218 | + assert(!UCharDeque_full(ud)); | |
219 | + } | |
220 | + | |
221 | + UCharDeque_delete(ud); | |
222 | +} | |
223 | + | |
224 | +void DequeTest_test_1_4(void) | |
225 | +{ | |
226 | + int i, j; | |
227 | + printf("***** test_1_4 *****\n"); | |
228 | + ud = UCharDeque_new(MAX); | |
229 | + for (j = 0; j < MAX+1; j++) { | |
230 | + ud->begin = ud->end = j; | |
231 | + assert(UCharDeque_size(ud) == 0); | |
232 | + /* insert */ | |
233 | + /* 空状態 */ | |
234 | + for (i = 0; i < MAX/2; i++) { | |
235 | + assert(ud_cmp(0, hoge, i) == 0); | |
236 | + assert(UCharDeque_insert(ud, i, hoge[i])); | |
237 | + } | |
238 | + /* 先頭・前寄り */ | |
239 | + assert(UCharDeque_insert(ud, 0, hoge[0])); | |
240 | + assert(UCharDeque_insert(ud, 1, hoge[1])); | |
241 | + assert(UCharDeque_insert(ud, 2, hoge[2])); | |
242 | + assert(ud_cmp(0, hoge, 3) == 0); | |
243 | + assert(ud_cmp(3, hoge, MAX/2) == 0); | |
244 | + assert(UCharDeque_size(ud) == MAX/2 + 3); | |
245 | + | |
246 | + /* erase */ | |
247 | + /* 先頭・前寄り */ | |
248 | + UCharDeque_erase(ud, 2); | |
249 | + assert(ud_cmp(0, hoge, 2) == 0); | |
250 | + assert(ud_cmp(2, hoge, MAX/2) == 0); | |
251 | + assert(UCharDeque_size(ud) == MAX/2 + 2); | |
252 | + UCharDeque_erase(ud, 1); | |
253 | + assert(ud_cmp(0, hoge, 1) == 0); | |
254 | + assert(ud_cmp(1, hoge, MAX/2) == 0); | |
255 | + assert(UCharDeque_size(ud) == MAX/2 + 1); | |
256 | + UCharDeque_erase(ud, 0); | |
257 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
258 | + assert(UCharDeque_size(ud) == MAX/2); | |
259 | + | |
260 | + /* insert */ | |
261 | + /* 末尾・後ろ寄り */ | |
262 | + assert(UCharDeque_insert(ud, MAX/2, hoge[0])); | |
263 | + assert(UCharDeque_insert(ud, MAX/2, hoge[1])); | |
264 | + assert(UCharDeque_insert(ud, MAX/2, hoge[2])); | |
265 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
266 | + assert(*UCharDeque_at(ud, MAX/2 + 0) == hoge[2]); | |
267 | + assert(*UCharDeque_at(ud, MAX/2 + 1) == hoge[1]); | |
268 | + assert(*UCharDeque_at(ud, MAX/2 + 2) == hoge[0]); | |
269 | + | |
270 | + /* erase */ | |
271 | + /* 末尾・後ろ寄り */ | |
272 | + UCharDeque_erase(ud, MAX/2); | |
273 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
274 | + assert(*UCharDeque_at(ud, MAX/2 + 0) == hoge[1]); | |
275 | + assert(*UCharDeque_at(ud, MAX/2 + 1) == hoge[0]); | |
276 | + assert(UCharDeque_size(ud) == MAX/2 + 2); | |
277 | + UCharDeque_erase(ud, MAX/2); | |
278 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
279 | + assert(*UCharDeque_at(ud, MAX/2 + 0) == hoge[0]); | |
280 | + assert(UCharDeque_size(ud) == MAX/2 + 1); | |
281 | + UCharDeque_erase(ud, MAX/2); | |
282 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
283 | + assert(UCharDeque_size(ud) == MAX/2); | |
284 | + | |
285 | + /* 先頭から全削除 */ | |
286 | + for (i = 0; i < MAX/2; i++) { | |
287 | + assert(ud_cmp(0, &hoge[i], MAX/2 - i) == 0); | |
288 | + UCharDeque_erase(ud, 0); | |
289 | + } | |
290 | + assert(UCharDeque_size(ud) == 0); | |
291 | + | |
292 | + for (i = 0; i < MAX/2; i++) { | |
293 | + assert(ud_cmp(0, hoge, i) == 0); | |
294 | + assert(UCharDeque_insert(ud, i, hoge[i])); | |
295 | + } | |
296 | + assert(UCharDeque_size(ud) == MAX/2); | |
297 | + | |
298 | + /* 末尾から全削除 */ | |
299 | + for (i = 0; i < MAX/2; i++) { | |
300 | + assert(ud_cmp(0, hoge, MAX/2 - i) == 0); | |
301 | + UCharDeque_erase(ud, UCharDeque_size(ud) -1); | |
302 | + } | |
303 | + assert(UCharDeque_size(ud) == 0); | |
304 | + | |
305 | + /* MAX以上で失敗 */ | |
306 | + assert(UCharDeque_assign(ud, hoge, MAX)); | |
307 | + assert(ud_cmp(0, hoge, MAX) == 0); | |
308 | + assert(UCharDeque_size(ud) == MAX); | |
309 | + assert(UCharDeque_full(ud)); | |
310 | + assert(!UCharDeque_insert(ud, 0, hoge[0])); | |
311 | + assert(ud_cmp(0, hoge, MAX) == 0); | |
312 | + assert(UCharDeque_size(ud) == MAX); | |
313 | + assert(UCharDeque_full(ud)); | |
314 | + } | |
315 | + | |
316 | + UCharDeque_delete(ud); | |
317 | +} | |
318 | + | |
319 | +void DequeTest_test_1_5(void) | |
320 | +{ | |
321 | + int i; | |
322 | + printf("***** test_1_5 *****\n"); | |
323 | + ud = UCharDeque_new(MAX); | |
324 | + for (i = 0; i < MAX+1; i++) { | |
325 | + ud->begin = ud->end = i; | |
326 | + assert(UCharDeque_size(ud) == 0); | |
327 | + /* insert_n */ | |
328 | + /* 空状態 */ | |
329 | + assert(UCharDeque_insert_n(ud, 0, hoge, MAX/2)); | |
330 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
331 | + assert(UCharDeque_size(ud) == MAX/2); | |
332 | + | |
333 | + /* insert_n */ | |
334 | + /* 先頭 */ | |
335 | + assert(UCharDeque_insert_n(ud, 0, hoge, 3)); | |
336 | + assert(ud_cmp(0, hoge, 3) == 0); | |
337 | + assert(ud_cmp(3, hoge, MAX/2) == 0); | |
338 | + assert(UCharDeque_size(ud) == MAX/2 + 3); | |
339 | + /* erase_n */ | |
340 | + UCharDeque_erase_n(ud, 0, 3); | |
341 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
342 | + assert(UCharDeque_size(ud) == MAX/2); | |
343 | + | |
344 | + /* insert_n */ | |
345 | + /* 前寄り */ | |
346 | + assert(UCharDeque_insert_n(ud, 2, hoge, 3)); | |
347 | + assert(ud_cmp(0, hoge, 2) == 0); | |
348 | + assert(ud_cmp(2, hoge, 3) == 0); | |
349 | + assert(ud_cmp(5, &hoge[2], MAX/2 -2) == 0); | |
350 | + assert(UCharDeque_size(ud) == MAX/2 + 3); | |
351 | + /* 0個指定 */ | |
352 | + assert(UCharDeque_insert_n(ud, 1, &hoge[MAX/2], 0)); | |
353 | + assert(ud_cmp(0, hoge, 2) == 0); | |
354 | + assert(ud_cmp(2, hoge, 3) == 0); | |
355 | + assert(ud_cmp(5, &hoge[2], MAX/2 -2) == 0); | |
356 | + assert(UCharDeque_size(ud) == MAX/2 + 3); | |
357 | + /* 1個指定 */ | |
358 | + assert(UCharDeque_insert_n(ud, 1, &hoge[MAX-1], 1)); | |
359 | + assert(ud_cmp(0, &hoge[0], 1) == 0); | |
360 | + assert(ud_cmp(1, &hoge[MAX-1], 1) == 0); | |
361 | + assert(ud_cmp(2, &hoge[1], 1) == 0); | |
362 | + assert(ud_cmp(3, &hoge[0], 3) == 0); | |
363 | + assert(ud_cmp(6, &hoge[2], MAX/2 -2) == 0); | |
364 | + assert(UCharDeque_size(ud) == MAX/2 + 4); | |
365 | + /* erase_n */ | |
366 | + /* 0個指定 */ | |
367 | + UCharDeque_erase_n(ud, 1, 0); | |
368 | + assert(ud_cmp(0, &hoge[0], 1) == 0); | |
369 | + assert(ud_cmp(1, &hoge[MAX-1], 1) == 0); | |
370 | + assert(ud_cmp(2, &hoge[1], 1) == 0); | |
371 | + assert(ud_cmp(3, &hoge[0], 3) == 0); | |
372 | + assert(ud_cmp(6, &hoge[2], MAX/2 -2) == 0); | |
373 | + assert(UCharDeque_size(ud) == MAX/2 + 4); | |
374 | + /* 1個指定 */ | |
375 | + UCharDeque_erase_n(ud, 1, 1); | |
376 | + assert(ud_cmp(0, hoge, 2) == 0); | |
377 | + assert(ud_cmp(2, hoge, 3) == 0); | |
378 | + assert(ud_cmp(5, &hoge[2], MAX/2 -2) == 0); | |
379 | + assert(UCharDeque_size(ud) == MAX/2 + 3); | |
380 | + /* 前寄り */ | |
381 | + UCharDeque_erase_n(ud, 2, 3); | |
382 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
383 | + assert(UCharDeque_size(ud) == MAX/2); | |
384 | + | |
385 | + /* insert_n */ | |
386 | + /* 末尾 */ | |
387 | + assert(UCharDeque_insert_n(ud, UCharDeque_size(ud), hoge, 3)); | |
388 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
389 | + assert(ud_cmp(MAX/2, hoge, 3) == 0); | |
390 | + assert(UCharDeque_size(ud) == MAX/2 + 3); | |
391 | + /* erase_n */ | |
392 | + UCharDeque_erase_n(ud, UCharDeque_size(ud) - 3, 3); | |
393 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
394 | + assert(UCharDeque_size(ud) == MAX/2); | |
395 | + | |
396 | + /* insert_n */ | |
397 | + /* 後ろ寄り */ | |
398 | + assert(UCharDeque_insert_n(ud, UCharDeque_size(ud) - 2, hoge, 3)); | |
399 | + assert(ud_cmp(0, hoge, MAX/2 -2) == 0); | |
400 | + assert(ud_cmp(MAX/2 -2, hoge, 3) == 0); | |
401 | + assert(ud_cmp(MAX/2 +1, &hoge[MAX/2 -2], 2) == 0); | |
402 | + assert(UCharDeque_size(ud) == MAX/2 + 3); | |
403 | + /* 0個指定 */ | |
404 | + assert(UCharDeque_insert_n(ud, UCharDeque_size(ud) - 1, &hoge[MAX-1], 0)); | |
405 | + assert(ud_cmp(0, hoge, MAX/2 -2) == 0); | |
406 | + assert(ud_cmp(MAX/2 -2, hoge, 3) == 0); | |
407 | + assert(ud_cmp(MAX/2 +1, &hoge[MAX/2 -2], 2) == 0); | |
408 | + assert(UCharDeque_size(ud) == MAX/2 + 3); | |
409 | + /* 1個指定 */ | |
410 | + assert(UCharDeque_insert_n(ud, UCharDeque_size(ud) - 1, &hoge[MAX-1], 1)); | |
411 | + assert(ud_cmp(0, hoge, MAX/2 -2) == 0); | |
412 | + assert(ud_cmp(MAX/2 -2, hoge, 3) == 0); | |
413 | + assert(ud_cmp(MAX/2 +1, &hoge[MAX/2 -2], 1) == 0); | |
414 | + assert(ud_cmp(MAX/2 +2, &hoge[MAX-1], 1) == 0); | |
415 | + assert(ud_cmp(MAX/2 +3, &hoge[MAX/2 -1], 1) == 0); | |
416 | + assert(UCharDeque_size(ud) == MAX/2 + 4); | |
417 | + /* erase_n */ | |
418 | + /* 0個指定 */ | |
419 | + UCharDeque_erase_n(ud, UCharDeque_size(ud) - 2, 0); | |
420 | + assert(ud_cmp(0, hoge, MAX/2 -2) == 0); | |
421 | + assert(ud_cmp(MAX/2 -2, hoge, 3) == 0); | |
422 | + assert(ud_cmp(MAX/2 +1, &hoge[MAX/2 -2], 1) == 0); | |
423 | + assert(ud_cmp(MAX/2 +2, &hoge[MAX-1], 1) == 0); | |
424 | + assert(ud_cmp(MAX/2 +3, &hoge[MAX/2 -1], 1) == 0); | |
425 | + assert(UCharDeque_size(ud) == MAX/2 + 4); | |
426 | + /* 1個指定 */ | |
427 | + UCharDeque_erase_n(ud, UCharDeque_size(ud) - 2, 1); | |
428 | + assert(ud_cmp(0, hoge, MAX/2 -2) == 0); | |
429 | + assert(ud_cmp(MAX/2 -2, hoge, 3) == 0); | |
430 | + assert(ud_cmp(MAX/2 +1, &hoge[MAX/2 -2], 2) == 0); | |
431 | + assert(UCharDeque_size(ud) == MAX/2 + 3); | |
432 | + /* 後ろ寄り */ | |
433 | + UCharDeque_erase_n(ud, UCharDeque_size(ud) - 5, 3); | |
434 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
435 | + assert(UCharDeque_size(ud) == MAX/2); | |
436 | + | |
437 | + /* MAX以上で失敗 */ | |
438 | + assert(!UCharDeque_insert_n(ud, 0, hoge, MAX - MAX/2 +1)); | |
439 | + assert(ud_cmp(0, hoge, MAX/2) == 0); | |
440 | + assert(UCharDeque_size(ud) == MAX/2); | |
441 | + /* MAXになるまで */ | |
442 | + assert(UCharDeque_insert_n(ud, 0, hoge, MAX - MAX/2)); | |
443 | + assert(UCharDeque_size(ud) == MAX); | |
444 | + assert(UCharDeque_full(ud)); | |
445 | + /* 先頭から全削除 */ | |
446 | + UCharDeque_erase_n(ud, 0, UCharDeque_size(ud)); | |
447 | + assert(UCharDeque_size(ud) == 0); | |
448 | + } | |
449 | + | |
450 | + UCharDeque_delete(ud); | |
451 | +} | |
452 | + | |
453 | +void DequeTest_test_1_6(void) | |
454 | +{ | |
455 | + int i; | |
456 | + UCharDeque *x; | |
457 | + printf("***** test_1_6 *****\n"); | |
458 | + ud = UCharDeque_new(MAX); | |
459 | + for (i = 0; i < MAX; i++) { | |
460 | + assert(UCharDeque_push_back(ud, hoge[i])); | |
461 | + } | |
462 | + /* new_copy */ | |
463 | + x = UCharDeque_new_copy(ud); | |
464 | + assert(UCharDeque_size(ud) == UCharDeque_size(x)); | |
465 | + assert(UCharDeque_max_size(ud) == UCharDeque_max_size(x)); | |
466 | + for (i = 0; i < UCharDeque_size(ud); i++) { | |
467 | + assert(*UCharDeque_at(x, i) == *UCharDeque_at(ud, i)); | |
468 | + } | |
469 | + /* resize */ | |
470 | + UCharDeque_clear(ud); | |
471 | + assert(UCharDeque_resize(ud, 64, 100)); | |
472 | + assert(UCharDeque_size(ud) == 64); | |
473 | + for (i = 0; i < UCharDeque_size(ud); i++) { | |
474 | + assert(*UCharDeque_at(ud, i) == 100); | |
475 | + } | |
476 | + assert(UCharDeque_resize(ud, 16, 99)); | |
477 | + assert(UCharDeque_size(ud) == 16); | |
478 | + for (i = 0; i < UCharDeque_size(ud); i++) { | |
479 | + assert(*UCharDeque_at(ud, i) == 100); | |
480 | + } | |
481 | + assert(UCharDeque_resize(ud, 32, 99)); | |
482 | + for (i = 0; i < UCharDeque_size(ud); i++) { | |
483 | + if (i < 16) { | |
484 | + assert(*UCharDeque_at(ud, i) == 100); | |
485 | + } else { | |
486 | + assert(*UCharDeque_at(ud, i) == 99); | |
487 | + } | |
488 | + } | |
489 | + assert(UCharDeque_size(ud) == 32); | |
490 | + assert(UCharDeque_resize(ud, MAX+1, 99) == 0); | |
491 | + assert(UCharDeque_resize(ud, 0, 100)); | |
492 | + assert(UCharDeque_size(ud) == 0); | |
493 | + | |
494 | + | |
495 | + UCharDeque_delete(ud); | |
496 | + UCharDeque_delete(x); | |
497 | +} | |
498 | + | |
499 | + | |
500 | + | |
501 | +void DequeTest_test_2_1(void) | |
502 | +{ | |
503 | + int i, j; | |
504 | + printf("***** test_2_1 *****\n"); | |
505 | + id = IntDeque_new(MAX); | |
506 | + /* 初期状態 */ | |
507 | + assert(IntDeque_max_size(id) == MAX); | |
508 | + assert(IntDeque_size(id) == 0); | |
509 | + assert(IntDeque_empty(id)); | |
510 | + assert(!IntDeque_full(id)); | |
511 | + for (j = 0; j < MAX+1; j++) { | |
512 | + id->begin = id->end = j; | |
513 | + assert(IntDeque_size(id) == 0); | |
514 | + /* assign */ | |
515 | + assert(IntDeque_assign(id, piyo, MAX)); | |
516 | + assert(id_cmp(0, piyo, MAX) == 0); | |
517 | + assert(IntDeque_size(id) == MAX); | |
518 | + assert(!IntDeque_empty(id)); | |
519 | + assert(IntDeque_full(id)); | |
520 | + /* at */ | |
521 | + for (i = 0; i < IntDeque_size(id); i++) { | |
522 | + assert(*IntDeque_at(id, i) == hoge[i]); | |
523 | + *IntDeque_at(id, i) = hoge[MAX - i -1]; | |
524 | + assert(*IntDeque_at(id, i) == hoge[MAX - i -1]); | |
525 | + } | |
526 | + /* clear */ | |
527 | + IntDeque_clear(id); | |
528 | + assert(IntDeque_size(id) == 0); | |
529 | + assert(IntDeque_empty(id)); | |
530 | + assert(!IntDeque_full(id)); | |
531 | + /* assign */ | |
532 | + assert(IntDeque_assign(id, piyo, MAX/2)); | |
533 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
534 | + assert(IntDeque_size(id) == MAX/2); | |
535 | + assert(!IntDeque_empty(id)); | |
536 | + assert(!IntDeque_full(id)); | |
537 | + /* MAX以上で失敗 */ | |
538 | + assert(!IntDeque_assign(id, piyo, MAX+1)); | |
539 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
540 | + assert(IntDeque_size(id) == MAX/2); | |
541 | + assert(!IntDeque_empty(id)); | |
542 | + assert(!IntDeque_full(id)); | |
543 | + /* clear */ | |
544 | + IntDeque_clear(id); | |
545 | + assert(IntDeque_size(id) == 0); | |
546 | + } | |
547 | + | |
548 | + IntDeque_delete(id); | |
549 | +} | |
550 | + | |
551 | +void DequeTest_test_2_2(void) | |
552 | +{ | |
553 | + int i, j; | |
554 | + size_t size; | |
555 | + printf("***** test_2_2 *****\n"); | |
556 | + id = IntDeque_new(MAX); | |
557 | + for (j = 0; j < MAX+1; j++) { | |
558 | + id->begin = id->end = j; | |
559 | + assert(IntDeque_size(id) == 0); | |
560 | + /* push_back */ | |
561 | + /* MAXまで */ | |
562 | + for (i = 0; i < MAX; i++) { | |
563 | + size = IntDeque_size(id); | |
564 | + assert(IntDeque_push_back(id, piyo[i])); | |
565 | + assert(IntDeque_size(id) == size + 1); | |
566 | + } | |
567 | + assert(id_cmp(0, piyo, MAX) == 0); | |
568 | + assert(IntDeque_size(id) == MAX); | |
569 | + assert(!IntDeque_empty(id)); | |
570 | + assert(IntDeque_full(id)); | |
571 | + /* FULLで失敗 */ | |
572 | + assert(!IntDeque_push_back(id, piyo[0])); | |
573 | + assert(IntDeque_size(id) == MAX); | |
574 | + assert(!IntDeque_empty(id)); | |
575 | + assert(IntDeque_full(id)); | |
576 | + /* front */ | |
577 | + assert(IntDeque_front(id) == piyo[0]); | |
578 | + /* back */ | |
579 | + assert(IntDeque_back(id) == piyo[MAX-1]); | |
580 | + /* pop_front */ | |
581 | + size = IntDeque_size(id); | |
582 | + assert(IntDeque_pop_front(id) == piyo[0]); | |
583 | + assert(IntDeque_size(id) == size - 1); | |
584 | + /* push_back */ | |
585 | + size = IntDeque_size(id); | |
586 | + assert(IntDeque_push_back(id, piyo[0])); | |
587 | + assert(IntDeque_size(id) == size + 1); | |
588 | + assert(id_cmp(0, &piyo[1], MAX-1) == 0); | |
589 | + assert(id_cmp(MAX-1, piyo, 1) == 0); | |
590 | + assert(IntDeque_size(id) == MAX); | |
591 | + assert(!IntDeque_empty(id)); | |
592 | + assert(IntDeque_full(id)); | |
593 | + /* pop_front */ | |
594 | + for (i = 0; i < MAX; i++) { | |
595 | + size = IntDeque_size(id); | |
596 | + if (i < MAX-1) { | |
597 | + assert(IntDeque_pop_front(id) == piyo[i+1]); | |
598 | + } else { | |
599 | + assert(IntDeque_pop_front(id) == piyo[0]); | |
600 | + } | |
601 | + assert(IntDeque_size(id) == size - 1); | |
602 | + } | |
603 | + assert(IntDeque_size(id) == 0); | |
604 | + assert(IntDeque_empty(id)); | |
605 | + assert(!IntDeque_full(id)); | |
606 | + } | |
607 | + | |
608 | + IntDeque_delete(id); | |
609 | +} | |
610 | + | |
611 | +void DequeTest_test_2_3(void) | |
612 | +{ | |
613 | + int i, j; | |
614 | + size_t size; | |
615 | + printf("***** test_2_3 *****\n"); | |
616 | + id = IntDeque_new(MAX); | |
617 | + for (j = 0; j < MAX+1; j++) { | |
618 | + id->begin = id->end = j; | |
619 | + assert(IntDeque_size(id) == 0); | |
620 | + /* push_front */ | |
621 | + /* MAXまで */ | |
622 | + for (i = 0; i < MAX; i++) { | |
623 | + size = IntDeque_size(id); | |
624 | + assert(IntDeque_push_front(id, piyo[MAX-i-1])); | |
625 | + assert(IntDeque_size(id) == size + 1); | |
626 | + } | |
627 | + assert(id_cmp(0, piyo, MAX) == 0); | |
628 | + assert(IntDeque_size(id) == MAX); | |
629 | + assert(!IntDeque_empty(id)); | |
630 | + assert(IntDeque_full(id)); | |
631 | + /* FULLで失敗 */ | |
632 | + assert(!IntDeque_push_front(id, piyo[0])); | |
633 | + assert(IntDeque_size(id) == MAX); | |
634 | + assert(!IntDeque_empty(id)); | |
635 | + assert(IntDeque_full(id)); | |
636 | + /* front */ | |
637 | + assert(IntDeque_front(id) == piyo[0]); | |
638 | + /* back */ | |
639 | + assert(IntDeque_back(id) == piyo[MAX-1]); | |
640 | + /* pop_back */ | |
641 | + size = IntDeque_size(id); | |
642 | + assert(IntDeque_pop_back(id) == piyo[MAX-1]); | |
643 | + assert(IntDeque_pop_back(id) == piyo[MAX-2]); | |
644 | + assert(IntDeque_size(id) == size - 2); | |
645 | + /* push_front */ | |
646 | + size = IntDeque_size(id); | |
647 | + assert(IntDeque_push_front(id, piyo[MAX-1])); | |
648 | + assert(IntDeque_push_front(id, piyo[MAX-2])); | |
649 | + assert(IntDeque_size(id) == size + 2); | |
650 | + assert(id_cmp(0, &piyo[MAX-2], 2) == 0); | |
651 | + assert(id_cmp(2, piyo, MAX-2) == 0); | |
652 | + assert(IntDeque_size(id) == MAX); | |
653 | + assert(!IntDeque_empty(id)); | |
654 | + assert(IntDeque_full(id)); | |
655 | + /* pop_back */ | |
656 | + for (i = MAX-3; i >= 0; i--) { | |
657 | + size = IntDeque_size(id); | |
658 | + assert(IntDeque_pop_back(id) == piyo[i]); | |
659 | + assert(IntDeque_size(id) == size - 1); | |
660 | + } | |
661 | + assert(IntDeque_pop_back(id) == piyo[MAX-1]); | |
662 | + assert(IntDeque_pop_back(id) == piyo[MAX-2]); | |
663 | + | |
664 | + assert(IntDeque_size(id) == 0); | |
665 | + assert(IntDeque_empty(id)); | |
666 | + assert(!IntDeque_full(id)); | |
667 | + } | |
668 | + | |
669 | + IntDeque_delete(id); | |
670 | +} | |
671 | + | |
672 | +void DequeTest_test_2_4(void) | |
673 | +{ | |
674 | + int i, j; | |
675 | + printf("***** test_2_4 *****\n"); | |
676 | + id = IntDeque_new(MAX); | |
677 | + for (j = 0; j < MAX+1; j++) { | |
678 | + id->begin = id->end = j; | |
679 | + assert(IntDeque_size(id) == 0); | |
680 | + /* insert */ | |
681 | + /* 空状態 */ | |
682 | + for (i = 0; i < MAX/2; i++) { | |
683 | + assert(id_cmp(0, piyo, i) == 0); | |
684 | + assert(IntDeque_insert(id, i, piyo[i])); | |
685 | + } | |
686 | + /* 先頭・前寄り */ | |
687 | + assert(IntDeque_insert(id, 0, piyo[0])); | |
688 | + assert(IntDeque_insert(id, 1, piyo[1])); | |
689 | + assert(IntDeque_insert(id, 2, piyo[2])); | |
690 | + assert(id_cmp(0, piyo, 3) == 0); | |
691 | + assert(id_cmp(3, piyo, MAX/2) == 0); | |
692 | + assert(IntDeque_size(id) == MAX/2 + 3); | |
693 | + | |
694 | + /* erase */ | |
695 | + /* 先頭・前寄り */ | |
696 | + IntDeque_erase(id, 2); | |
697 | + assert(id_cmp(0, piyo, 2) == 0); | |
698 | + assert(id_cmp(2, piyo, MAX/2) == 0); | |
699 | + assert(IntDeque_size(id) == MAX/2 + 2); | |
700 | + IntDeque_erase(id, 1); | |
701 | + assert(id_cmp(0, piyo, 1) == 0); | |
702 | + assert(id_cmp(1, piyo, MAX/2) == 0); | |
703 | + assert(IntDeque_size(id) == MAX/2 + 1); | |
704 | + IntDeque_erase(id, 0); | |
705 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
706 | + assert(IntDeque_size(id) == MAX/2); | |
707 | + | |
708 | + /* insert */ | |
709 | + /* 末尾・後ろ寄り */ | |
710 | + assert(IntDeque_insert(id, MAX/2, piyo[0])); | |
711 | + assert(IntDeque_insert(id, MAX/2, piyo[1])); | |
712 | + assert(IntDeque_insert(id, MAX/2, piyo[2])); | |
713 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
714 | + assert(*IntDeque_at(id, MAX/2 + 0) == piyo[2]); | |
715 | + assert(*IntDeque_at(id, MAX/2 + 1) == piyo[1]); | |
716 | + assert(*IntDeque_at(id, MAX/2 + 2) == piyo[0]); | |
717 | + | |
718 | + /* erase */ | |
719 | + /* 末尾・後ろ寄り */ | |
720 | + IntDeque_erase(id, MAX/2); | |
721 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
722 | + assert(*IntDeque_at(id, MAX/2 + 0) == piyo[1]); | |
723 | + assert(*IntDeque_at(id, MAX/2 + 1) == piyo[0]); | |
724 | + assert(IntDeque_size(id) == MAX/2 + 2); | |
725 | + IntDeque_erase(id, MAX/2); | |
726 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
727 | + assert(*IntDeque_at(id, MAX/2 + 0) == piyo[0]); | |
728 | + assert(IntDeque_size(id) == MAX/2 + 1); | |
729 | + IntDeque_erase(id, MAX/2); | |
730 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
731 | + assert(IntDeque_size(id) == MAX/2); | |
732 | + | |
733 | + /* 先頭から全削除 */ | |
734 | + for (i = 0; i < MAX/2; i++) { | |
735 | + assert(id_cmp(0, &piyo[i], MAX/2 - i) == 0); | |
736 | + IntDeque_erase(id, 0); | |
737 | + } | |
738 | + assert(IntDeque_size(id) == 0); | |
739 | + | |
740 | + for (i = 0; i < MAX/2; i++) { | |
741 | + assert(id_cmp(0, piyo, i) == 0); | |
742 | + assert(IntDeque_insert(id, i, piyo[i])); | |
743 | + } | |
744 | + assert(IntDeque_size(id) == MAX/2); | |
745 | + | |
746 | + /* 末尾から全削除 */ | |
747 | + for (i = 0; i < MAX/2; i++) { | |
748 | + assert(id_cmp(0, piyo, MAX/2 - i) == 0); | |
749 | + IntDeque_erase(id, IntDeque_size(id) -1); | |
750 | + } | |
751 | + assert(IntDeque_size(id) == 0); | |
752 | + | |
753 | + /* MAX以上で失敗 */ | |
754 | + assert(IntDeque_assign(id, piyo, MAX)); | |
755 | + assert(id_cmp(0, piyo, MAX) == 0); | |
756 | + assert(IntDeque_size(id) == MAX); | |
757 | + assert(IntDeque_full(id)); | |
758 | + assert(!IntDeque_insert(id, 0, piyo[0])); | |
759 | + assert(id_cmp(0, piyo, MAX) == 0); | |
760 | + assert(IntDeque_size(id) == MAX); | |
761 | + assert(IntDeque_full(id)); | |
762 | + } | |
763 | + | |
764 | + IntDeque_delete(id); | |
765 | +} | |
766 | + | |
767 | +void DequeTest_test_2_5(void) | |
768 | +{ | |
769 | + int i; | |
770 | + printf("***** test_2_5 *****\n"); | |
771 | + id = IntDeque_new(MAX); | |
772 | + for (i = 0; i < MAX+1; i++) { | |
773 | + id->begin = id->end = i; | |
774 | + assert(IntDeque_size(id) == 0); | |
775 | + /* insert_n */ | |
776 | + /* 空状態 */ | |
777 | + assert(IntDeque_insert_n(id, 0, piyo, MAX/2)); | |
778 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
779 | + assert(IntDeque_size(id) == MAX/2); | |
780 | + | |
781 | + /* insert_n */ | |
782 | + /* 先頭 */ | |
783 | + assert(IntDeque_insert_n(id, 0, piyo, 3)); | |
784 | + assert(id_cmp(0, piyo, 3) == 0); | |
785 | + assert(id_cmp(3, piyo, MAX/2) == 0); | |
786 | + assert(IntDeque_size(id) == MAX/2 + 3); | |
787 | + /* erase_n */ | |
788 | + IntDeque_erase_n(id, 0, 3); | |
789 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
790 | + assert(IntDeque_size(id) == MAX/2); | |
791 | + | |
792 | + /* insert_n */ | |
793 | + /* 前寄り */ | |
794 | + assert(IntDeque_insert_n(id, 2, piyo, 3)); | |
795 | + assert(id_cmp(0, piyo, 2) == 0); | |
796 | + assert(id_cmp(2, piyo, 3) == 0); | |
797 | + assert(id_cmp(5, &piyo[2], MAX/2 -2) == 0); | |
798 | + assert(IntDeque_size(id) == MAX/2 + 3); | |
799 | + /* 0個指定 */ | |
800 | + assert(IntDeque_insert_n(id, 1, &piyo[MAX/2], 0)); | |
801 | + assert(id_cmp(0, piyo, 2) == 0); | |
802 | + assert(id_cmp(2, piyo, 3) == 0); | |
803 | + assert(id_cmp(5, &piyo[2], MAX/2 -2) == 0); | |
804 | + assert(IntDeque_size(id) == MAX/2 + 3); | |
805 | + /* 1個指定 */ | |
806 | + assert(IntDeque_insert_n(id, 1, &piyo[MAX-1], 1)); | |
807 | + assert(id_cmp(0, &piyo[0], 1) == 0); | |
808 | + assert(id_cmp(1, &piyo[MAX-1], 1) == 0); | |
809 | + assert(id_cmp(2, &piyo[1], 1) == 0); | |
810 | + assert(id_cmp(3, &piyo[0], 3) == 0); | |
811 | + assert(id_cmp(6, &piyo[2], MAX/2 -2) == 0); | |
812 | + assert(IntDeque_size(id) == MAX/2 + 4); | |
813 | + /* erase_n */ | |
814 | + /* 0個指定 */ | |
815 | + IntDeque_erase_n(id, 1, 0); | |
816 | + assert(id_cmp(0, &piyo[0], 1) == 0); | |
817 | + assert(id_cmp(1, &piyo[MAX-1], 1) == 0); | |
818 | + assert(id_cmp(2, &piyo[1], 1) == 0); | |
819 | + assert(id_cmp(3, &piyo[0], 3) == 0); | |
820 | + assert(id_cmp(6, &piyo[2], MAX/2 -2) == 0); | |
821 | + assert(IntDeque_size(id) == MAX/2 + 4); | |
822 | + /* 1個指定 */ | |
823 | + IntDeque_erase_n(id, 1, 1); | |
824 | + assert(id_cmp(0, piyo, 2) == 0); | |
825 | + assert(id_cmp(2, piyo, 3) == 0); | |
826 | + assert(id_cmp(5, &piyo[2], MAX/2 -2) == 0); | |
827 | + assert(IntDeque_size(id) == MAX/2 + 3); | |
828 | + /* 前寄り */ | |
829 | + IntDeque_erase_n(id, 2, 3); | |
830 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
831 | + assert(IntDeque_size(id) == MAX/2); | |
832 | + | |
833 | + /* insert_n */ | |
834 | + /* 末尾 */ | |
835 | + assert(IntDeque_insert_n(id, IntDeque_size(id), piyo, 3)); | |
836 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
837 | + assert(id_cmp(MAX/2, piyo, 3) == 0); | |
838 | + assert(IntDeque_size(id) == MAX/2 + 3); | |
839 | + /* erase_n */ | |
840 | + IntDeque_erase_n(id, IntDeque_size(id) - 3, 3); | |
841 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
842 | + assert(IntDeque_size(id) == MAX/2); | |
843 | + | |
844 | + /* insert_n */ | |
845 | + /* 後ろ寄り */ | |
846 | + assert(IntDeque_insert_n(id, IntDeque_size(id) - 2, piyo, 3)); | |
847 | + assert(id_cmp(0, piyo, MAX/2 -2) == 0); | |
848 | + assert(id_cmp(MAX/2 -2, piyo, 3) == 0); | |
849 | + assert(id_cmp(MAX/2 +1, &piyo[MAX/2 -2], 2) == 0); | |
850 | + assert(IntDeque_size(id) == MAX/2 + 3); | |
851 | + /* 0個指定 */ | |
852 | + assert(IntDeque_insert_n(id, IntDeque_size(id) - 1, &piyo[MAX-1], 0)); | |
853 | + assert(id_cmp(0, piyo, MAX/2 -2) == 0); | |
854 | + assert(id_cmp(MAX/2 -2, piyo, 3) == 0); | |
855 | + assert(id_cmp(MAX/2 +1, &piyo[MAX/2 -2], 2) == 0); | |
856 | + assert(IntDeque_size(id) == MAX/2 + 3); | |
857 | + /* 1個指定 */ | |
858 | + assert(IntDeque_insert_n(id, IntDeque_size(id) - 1, &piyo[MAX-1], 1)); | |
859 | + assert(id_cmp(0, piyo, MAX/2 -2) == 0); | |
860 | + assert(id_cmp(MAX/2 -2, piyo, 3) == 0); | |
861 | + assert(id_cmp(MAX/2 +1, &piyo[MAX/2 -2], 1) == 0); | |
862 | + assert(id_cmp(MAX/2 +2, &piyo[MAX-1], 1) == 0); | |
863 | + assert(id_cmp(MAX/2 +3, &piyo[MAX/2 -1], 1) == 0); | |
864 | + assert(IntDeque_size(id) == MAX/2 + 4); | |
865 | + /* erase_n */ | |
866 | + /* 0個指定 */ | |
867 | + IntDeque_erase_n(id, IntDeque_size(id) - 2, 0); | |
868 | + assert(id_cmp(0, piyo, MAX/2 -2) == 0); | |
869 | + assert(id_cmp(MAX/2 -2, piyo, 3) == 0); | |
870 | + assert(id_cmp(MAX/2 +1, &piyo[MAX/2 -2], 1) == 0); | |
871 | + assert(id_cmp(MAX/2 +2, &piyo[MAX-1], 1) == 0); | |
872 | + assert(id_cmp(MAX/2 +3, &piyo[MAX/2 -1], 1) == 0); | |
873 | + assert(IntDeque_size(id) == MAX/2 + 4); | |
874 | + /* 1個指定 */ | |
875 | + IntDeque_erase_n(id, IntDeque_size(id) - 2, 1); | |
876 | + assert(id_cmp(0, piyo, MAX/2 -2) == 0); | |
877 | + assert(id_cmp(MAX/2 -2, piyo, 3) == 0); | |
878 | + assert(id_cmp(MAX/2 +1, &piyo[MAX/2 -2], 2) == 0); | |
879 | + assert(IntDeque_size(id) == MAX/2 + 3); | |
880 | + /* 後ろ寄り */ | |
881 | + IntDeque_erase_n(id, IntDeque_size(id) - 5, 3); | |
882 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
883 | + assert(IntDeque_size(id) == MAX/2); | |
884 | + | |
885 | + /* MAX以上で失敗 */ | |
886 | + assert(!IntDeque_insert_n(id, 0, piyo, MAX - MAX/2 +1)); | |
887 | + assert(id_cmp(0, piyo, MAX/2) == 0); | |
888 | + assert(IntDeque_size(id) == MAX/2); | |
889 | + /* MAXになるまで */ | |
890 | + assert(IntDeque_insert_n(id, 0, piyo, MAX - MAX/2)); | |
891 | + assert(IntDeque_size(id) == MAX); | |
892 | + assert(IntDeque_full(id)); | |
893 | + /* 先頭から全削除 */ | |
894 | + IntDeque_erase_n(id, 0, IntDeque_size(id)); | |
895 | + assert(IntDeque_size(id) == 0); | |
896 | + } | |
897 | + | |
898 | + IntDeque_delete(id); | |
899 | +} | |
900 | + | |
901 | + | |
902 | + | |
903 | + | |
904 | + | |
905 | + | |
906 | +void DequeTest_run(void) | |
907 | +{ | |
908 | + printf("\n===== deque test =====\n"); | |
909 | + deque_init_hoge(); | |
910 | + deque_init_piyo(); | |
911 | + | |
912 | + DequeTest_test_1_1(); | |
913 | + DequeTest_test_1_2(); | |
914 | + DequeTest_test_1_3(); | |
915 | + DequeTest_test_1_4(); | |
916 | + DequeTest_test_1_5(); | |
917 | + DequeTest_test_1_6(); | |
918 | + | |
919 | + DequeTest_test_2_1(); | |
920 | + DequeTest_test_2_2(); | |
921 | + DequeTest_test_2_3(); | |
922 | + DequeTest_test_2_4(); | |
923 | + DequeTest_test_2_5(); | |
924 | +} | |
925 | + |
@@ -0,0 +1,77 @@ | ||
1 | +#ifndef TEST_H_INCLUDED | |
2 | +#define TEST_H_INCLUDED | |
3 | + | |
4 | +#include <stdio.h> | |
5 | +#include <string.h> | |
6 | +#include <assert.h> | |
7 | +#include "../cstl/vector.h" | |
8 | +#include "../cstl/deque.h" | |
9 | +#include "../cstl/list.h" | |
10 | +#include "../cstl/set.h" | |
11 | +#include "../cstl/map.h" | |
12 | +#include "rbtree_debug.h" | |
13 | +#include "../heap.h" | |
14 | +#ifdef MY_MALLOC | |
15 | +extern Heap heap; | |
16 | +#define malloc(s) Heap_alloc(&heap, s) | |
17 | +#define realloc(p, s) Heap_realloc(&heap, p, s) | |
18 | +#define free(p) Heap_free(&heap, p) | |
19 | +#endif | |
20 | + | |
21 | +/* vector */ | |
22 | +VECTOR_INTERFACE(UCharVector, unsigned char) | |
23 | +VECTOR_INTERFACE(IntVector, int) | |
24 | + | |
25 | + | |
26 | +/* deque */ | |
27 | +DEQUE_INTERFACE(UCharDeque, unsigned char) | |
28 | +DEQUE_INTERFACE(IntDeque, int) | |
29 | + | |
30 | + | |
31 | +/* list */ | |
32 | +typedef struct Hoge_t { | |
33 | + char *key; | |
34 | + int value; | |
35 | +} Hoge; | |
36 | + | |
37 | +LIST_INTERFACE(UCharList, unsigned char) | |
38 | +LIST_INTERFACE(IntList, int) | |
39 | +LIST_INTERFACE(StrList, char *) | |
40 | +LIST_INTERFACE(HogeList, Hoge) | |
41 | + | |
42 | + | |
43 | +/* set */ | |
44 | +SET_INTERFACE(IntSetA, int) | |
45 | +SET_DEBUG_INTERFACE(IntSetA) | |
46 | + | |
47 | +SET_INTERFACE(IntSetD, int) | |
48 | +SET_DEBUG_INTERFACE(IntSetD) | |
49 | + | |
50 | +MULTISET_INTERFACE(IntMSetA, int) | |
51 | +SET_DEBUG_INTERFACE(IntMSetA) | |
52 | + | |
53 | +SET_INTERFACE(DoubleSetA, double) | |
54 | +SET_DEBUG_INTERFACE(DoubleSetA) | |
55 | + | |
56 | +SET_INTERFACE(PtrSetA, int*) | |
57 | +SET_DEBUG_INTERFACE(PtrSetA) | |
58 | + | |
59 | +SET_INTERFACE(StrSetA, char*) | |
60 | +SET_DEBUG_INTERFACE(StrSetA) | |
61 | + | |
62 | + | |
63 | +/* map */ | |
64 | +MAP_INTERFACE(IntIntMapA, int, int) | |
65 | +MAP_DEBUG_INTERFACE(IntIntMapA) | |
66 | + | |
67 | +MULTIMAP_INTERFACE(IntIntMMapA, int, int) | |
68 | +MAP_DEBUG_INTERFACE(IntIntMMapA) | |
69 | + | |
70 | + | |
71 | +void VectorTest_run(void); | |
72 | +void DequeTest_run(void); | |
73 | +void ListTest_run(void); | |
74 | +void SetTest_run(void); | |
75 | +void MapTest_run(void); | |
76 | + | |
77 | +#endif /* TEST_H_INCLUDED */ |
@@ -0,0 +1,22 @@ | ||
1 | +#include "test.h" | |
2 | + | |
3 | +char buf[1024*1024]; | |
4 | +Heap heap; | |
5 | + | |
6 | +int main(void) | |
7 | +{ | |
8 | +#ifdef MY_MALLOC | |
9 | + Heap_init(&heap, buf, sizeof buf); | |
10 | +#endif | |
11 | + | |
12 | + VectorTest_run(); | |
13 | + DequeTest_run(); | |
14 | + ListTest_run(); | |
15 | + SetTest_run(); | |
16 | + MapTest_run(); | |
17 | + | |
18 | +#ifdef MY_MALLOC | |
19 | + DUMP_MEMORY_LEAK(&heap, 0); | |
20 | +#endif | |
21 | + return 0; | |
22 | +} |
@@ -0,0 +1,528 @@ | ||
1 | +#include "../cstl/string.h" | |
2 | +#include <assert.h> | |
3 | +#include <stdio.h> | |
4 | +#include <string.h> | |
5 | +#include <string> | |
6 | + | |
7 | +#include "../heap.h" | |
8 | +#ifdef MY_MALLOC | |
9 | +extern Heap heap; | |
10 | +#define malloc(s) Heap_alloc(&heap, s) | |
11 | +#define realloc(p, s) Heap_realloc(&heap, p, s) | |
12 | +#define free(p) Heap_free(&heap, p) | |
13 | +#endif | |
14 | + | |
15 | +STRING_INTERFACE(String, char) | |
16 | +STRING_IMPLEMENT(String, char) | |
17 | + | |
18 | + | |
19 | +using namespace std; | |
20 | + | |
21 | + | |
22 | +void StringTest_test_1_1(void) | |
23 | +{ | |
24 | + String *x; | |
25 | + String *y; | |
26 | + string s; | |
27 | + size_t i; | |
28 | + printf("***** test_1_1 *****\n"); | |
29 | + /* 初期状態 */ | |
30 | + x = String_new(); | |
31 | + assert(String_empty(x)); | |
32 | + assert(String_size(x) == 0); | |
33 | + String_delete(x); | |
34 | + /* new_cstr */ | |
35 | + x = String_new_cstr("", NPOS); | |
36 | + assert(String_empty(x)); | |
37 | + assert(String_size(x) == 0); | |
38 | + String_delete(x); | |
39 | + x = String_new_cstr("abcdef", NPOS); | |
40 | + assert(!String_empty(x)); | |
41 | + assert(String_size(x) == 6); | |
42 | + assert(String_size(x) == String_length(x)); | |
43 | + String_delete(x); | |
44 | + x = String_new_cstr("abcdef", 0); | |
45 | + assert(strcmp(String_c_str(x), "") == 0); | |
46 | + String_delete(x); | |
47 | + x = String_new_cstr("abcdefghijklmn", 7); | |
48 | + assert(strcmp(String_c_str(x), "abcdefg") == 0); | |
49 | + /* new_copy */ | |
50 | + y = String_new_copy(x); | |
51 | + assert(strcmp(String_c_str(y), "abcdefg") == 0); | |
52 | + assert(!String_empty(y)); | |
53 | + assert(String_size(y) == 7); | |
54 | + String_delete(y); | |
55 | + /* new_c */ | |
56 | + y = String_new_c(10, 'a'); | |
57 | + assert(strcmp(String_c_str(y), "aaaaaaaaaa") == 0); | |
58 | + assert(String_size(y) == 10); | |
59 | + String_delete(y); | |
60 | + y = String_new_c(0, 'b'); | |
61 | + assert(strcmp(String_c_str(y), "") == 0); | |
62 | + assert(String_size(y) == 0); | |
63 | + String_delete(y); | |
64 | + y = String_new_c(1, 'c'); | |
65 | + assert(strcmp(String_c_str(y), "c") == 0); | |
66 | + assert(String_size(y) == 1); | |
67 | + /* c_str */ | |
68 | +// printf("%s\n", String_c_str(x)); | |
69 | + s = String_c_str(x); | |
70 | + assert(strcmp(s.c_str(), String_c_str(x)) == 0); | |
71 | + /* at */ | |
72 | + for (i = 0; i < String_length(x); i++) { | |
73 | + assert(s.at(i) == *String_at(x, i)); | |
74 | + } | |
75 | + /* clear */ | |
76 | + String_clear(x); | |
77 | + assert(String_empty(x)); | |
78 | + assert(String_size(x) == 0); | |
79 | + | |
80 | + String_delete(x); | |
81 | + String_delete(y); | |
82 | +} | |
83 | + | |
84 | +void StringTest_test_1_2(void) | |
85 | +{ | |
86 | + String *x; | |
87 | + String *y; | |
88 | + printf("***** test_1_2 *****\n"); | |
89 | + x = String_new(); | |
90 | + /* capacity */ | |
91 | + /* reserve */ | |
92 | + String_reserve(x, 100); | |
93 | + assert(String_size(x) == 0); | |
94 | + assert(String_capacity(x) == 100); | |
95 | + String_reserve(x, 99); | |
96 | + assert(String_capacity(x) == 100); | |
97 | + String_reserve(x, 101); | |
98 | + assert(String_capacity(x) == 101); | |
99 | + /* shrink */ | |
100 | + String_shrink(x, 10); | |
101 | + assert(String_capacity(x) == 10); | |
102 | + String_shrink(x, 11); | |
103 | + assert(String_capacity(x) == 10); | |
104 | + String_shrink(x, 9); | |
105 | + assert(String_capacity(x) == 9); | |
106 | + /* resize */ | |
107 | + String_resize(x, 10, 'a'); | |
108 | + assert(String_size(x) == 10); | |
109 | + assert(strcmp("aaaaaaaaaa", String_c_str(x)) == 0); | |
110 | + String_resize(x, 15, 'b'); | |
111 | + assert(String_size(x) == 15); | |
112 | + assert(strcmp("aaaaaaaaaabbbbb", String_c_str(x)) == 0); | |
113 | + String_resize(x, 5, 'b'); | |
114 | + assert(String_size(x) == 5); | |
115 | + assert(strcmp("aaaaa", String_c_str(x)) == 0); | |
116 | + String_resize(x, 0, 'b'); | |
117 | + assert(String_size(x) == 0); | |
118 | + assert(strcmp("", String_c_str(x)) == 0); | |
119 | + /* assign */ | |
120 | + String_assign(x, "abcdefghijklmnopqrstuvwxyz", NPOS); | |
121 | + assert(String_size(x) == 26); | |
122 | + assert(strcmp("abcdefghijklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
123 | + /* erase */ | |
124 | + String_erase(x, 0, 3); | |
125 | + assert(String_size(x) == 23); | |
126 | + assert(strcmp("defghijklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
127 | + String_erase(x, 0, 0); | |
128 | + assert(String_size(x) == 23); | |
129 | + assert(strcmp("defghijklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
130 | + String_erase(x, 1, 1); | |
131 | + assert(String_size(x) == 22); | |
132 | + assert(strcmp("dfghijklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
133 | + String_erase(x, 5, 10); | |
134 | + assert(String_size(x) == 12); | |
135 | + assert(strcmp("dfghituvwxyz", String_c_str(x)) == 0); | |
136 | + String_erase(x, 11, 1); | |
137 | + assert(String_size(x) == 11); | |
138 | + assert(strcmp("dfghituvwxy", String_c_str(x)) == 0); | |
139 | + String_erase(x, 5, NPOS); | |
140 | + assert(String_size(x) == 5); | |
141 | + assert(strcmp("dfghi", String_c_str(x)) == 0); | |
142 | + String_erase(x, 0, NPOS); | |
143 | + assert(String_size(x) == 0); | |
144 | + assert(strcmp("", String_c_str(x)) == 0); | |
145 | + /* compare */ | |
146 | + String_assign(x, "abcdefg", NPOS); | |
147 | + y = String_new_cstr("abcdefgh", NPOS); | |
148 | + assert(String_compare(x, y) < 0); | |
149 | + String_erase(y, String_size(y)-2, 2); | |
150 | + assert(String_compare(x, y) > 0); | |
151 | + String_erase(x, String_size(x)-1, 1); | |
152 | + assert(String_compare(x, y) == 0); | |
153 | + | |
154 | + String_delete(x); | |
155 | + String_delete(y); | |
156 | +} | |
157 | + | |
158 | +void StringTest_test_1_3(void) | |
159 | +{ | |
160 | + String *x; | |
161 | + printf("***** test_1_3 *****\n"); | |
162 | + x = String_new(); | |
163 | + /* assign */ | |
164 | + String_assign(x, "abcdefghijklmnopqrstuvwxyz", NPOS); | |
165 | + assert(String_size(x) == 26); | |
166 | + assert(strcmp("abcdefghijklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
167 | + String_assign(x, "abcdefghijklmnopqrstuvwxyz", 10); | |
168 | + assert(String_size(x) == 10); | |
169 | + assert(strcmp("abcdefghij", String_c_str(x)) == 0); | |
170 | + String_assign(x, "abcdefghijklmnopqrstuvwxyz", 0); | |
171 | + assert(String_size(x) == 0); | |
172 | + assert(strcmp("", String_c_str(x)) == 0); | |
173 | + String_assign(x, "", 0); | |
174 | + assert(String_size(x) == 0); | |
175 | + assert(strcmp("", String_c_str(x)) == 0); | |
176 | + /* assign_c */ | |
177 | + String_assign_c(x, 10, 'a'); | |
178 | + assert(String_size(x) == 10); | |
179 | + assert(strcmp("aaaaaaaaaa", String_c_str(x)) == 0); | |
180 | + String_assign_c(x, 1, 'b'); | |
181 | + assert(String_size(x) == 1); | |
182 | + assert(strcmp("b", String_c_str(x)) == 0); | |
183 | + String_assign_c(x, 0, 'c'); | |
184 | + assert(String_size(x) == 0); | |
185 | + assert(strcmp("", String_c_str(x)) == 0); | |
186 | + /* append */ | |
187 | + String_append(x, "abcdef", NPOS); | |
188 | + assert(String_size(x) == 6); | |
189 | + assert(strcmp("abcdef", String_c_str(x)) == 0); | |
190 | + String_append(x, "gh", NPOS); | |
191 | + assert(String_size(x) == 8); | |
192 | + assert(strcmp("abcdefgh", String_c_str(x)) == 0); | |
193 | + String_append(x, "ijkl", 3); | |
194 | + assert(String_size(x) == 11); | |
195 | + assert(strcmp("abcdefghijk", String_c_str(x)) == 0); | |
196 | + String_append(x, "l", 1); | |
197 | + assert(String_size(x) == 12); | |
198 | + assert(strcmp("abcdefghijkl", String_c_str(x)) == 0); | |
199 | + String_append(x, "mno", 0); | |
200 | + assert(String_size(x) == 12); | |
201 | + assert(strcmp("abcdefghijkl", String_c_str(x)) == 0); | |
202 | + String_append(x, "m", NPOS); | |
203 | + assert(String_size(x) == 13); | |
204 | + assert(strcmp("abcdefghijklm", String_c_str(x)) == 0); | |
205 | + String_clear(x); | |
206 | + assert(String_size(x) == 0); | |
207 | + /* append_c */ | |
208 | + String_append_c(x, 5, 'a'); | |
209 | + assert(String_size(x) == 5); | |
210 | + assert(strcmp("aaaaa", String_c_str(x)) == 0); | |
211 | + String_append_c(x, 2, 'b'); | |
212 | + assert(String_size(x) == 7); | |
213 | + assert(strcmp("aaaaabb", String_c_str(x)) == 0); | |
214 | + String_append_c(x, 4, 'c'); | |
215 | + assert(String_size(x) == 11); | |
216 | + assert(strcmp("aaaaabbcccc", String_c_str(x)) == 0); | |
217 | + String_append_c(x, 0, 'd'); | |
218 | + assert(String_size(x) == 11); | |
219 | + assert(strcmp("aaaaabbcccc", String_c_str(x)) == 0); | |
220 | + /* push_back */ | |
221 | + String_push_back(x, 'd'); | |
222 | + String_push_back(x, 'e'); | |
223 | + String_push_back(x, 'f'); | |
224 | + assert(String_size(x) == 14); | |
225 | + assert(strcmp("aaaaabbccccdef", String_c_str(x)) == 0); | |
226 | + String_clear(x); | |
227 | + assert(String_size(x) == 0); | |
228 | + /* insert */ | |
229 | + String_insert(x, 0, "abcdef", NPOS); | |
230 | + assert(String_size(x) == 6); | |
231 | + assert(strcmp("abcdef", String_c_str(x)) == 0); | |
232 | + String_insert(x, 0, "gh", NPOS); | |
233 | + assert(String_size(x) == 8); | |
234 | + assert(strcmp("ghabcdef", String_c_str(x)) == 0); | |
235 | + String_insert(x, 1, "ijk", NPOS); | |
236 | + assert(String_size(x) == 11); | |
237 | + assert(strcmp("gijkhabcdef", String_c_str(x)) == 0); | |
238 | + String_insert(x, String_size(x), "lmn", NPOS); | |
239 | + assert(String_size(x) == 14); | |
240 | + assert(strcmp("gijkhabcdeflmn", String_c_str(x)) == 0); | |
241 | + String_insert(x, String_size(x)-1, "opqr", 3); | |
242 | + assert(String_size(x) == 17); | |
243 | + assert(strcmp("gijkhabcdeflmopqn", String_c_str(x)) == 0); | |
244 | + String_insert(x, 5, "rst", 0); | |
245 | + assert(String_size(x) == 17); | |
246 | + assert(strcmp("gijkhabcdeflmopqn", String_c_str(x)) == 0); | |
247 | + String_clear(x); | |
248 | + assert(String_size(x) == 0); | |
249 | + /* insert_c */ | |
250 | + String_insert_c(x, 0, 5, 'a'); | |
251 | + assert(String_size(x) == 5); | |
252 | + assert(strcmp("aaaaa", String_c_str(x)) == 0); | |
253 | + String_insert_c(x, 0, 3, 'b'); | |
254 | + assert(String_size(x) == 8); | |
255 | + assert(strcmp("bbbaaaaa", String_c_str(x)) == 0); | |
256 | + String_insert_c(x, 1, 2, 'c'); | |
257 | + assert(String_size(x) == 10); | |
258 | + assert(strcmp("bccbbaaaaa", String_c_str(x)) == 0); | |
259 | + String_insert_c(x, 2, 1, 'd'); | |
260 | + assert(String_size(x) == 11); | |
261 | + assert(strcmp("bcdcbbaaaaa", String_c_str(x)) == 0); | |
262 | + String_insert_c(x, String_size(x), 3, 'e'); | |
263 | + assert(String_size(x) == 14); | |
264 | + assert(strcmp("bcdcbbaaaaaeee", String_c_str(x)) == 0); | |
265 | + String_insert_c(x, String_size(x)-1, 2, 'f'); | |
266 | + assert(String_size(x) == 16); | |
267 | + assert(strcmp("bcdcbbaaaaaeeffe", String_c_str(x)) == 0); | |
268 | + String_insert_c(x, 5, 0, 'g'); | |
269 | + assert(String_size(x) == 16); | |
270 | + assert(strcmp("bcdcbbaaaaaeeffe", String_c_str(x)) == 0); | |
271 | + String_insert_c(x, 0, 17, 'g'); | |
272 | + assert(String_size(x) == 33); | |
273 | + assert(strcmp("gggggggggggggggggbcdcbbaaaaaeeffe", String_c_str(x)) == 0); | |
274 | + String_clear(x); | |
275 | + assert(String_size(x) == 0); | |
276 | + | |
277 | + | |
278 | +#if 0 | |
279 | + string s; | |
280 | + s.insert(0, "abc", 3); | |
281 | + printf("%s\n", s.c_str()); | |
282 | + s.insert(0, "def", 3); | |
283 | + printf("%s\n", s.c_str()); | |
284 | + s.erase(0, string::npos); | |
285 | + printf("%s\n", s.c_str()); | |
286 | +#endif | |
287 | + | |
288 | + String_delete(x); | |
289 | +} | |
290 | + | |
291 | +void StringTest_test_1_4(void) | |
292 | +{ | |
293 | + String *x; | |
294 | + printf("***** test_1_4 *****\n"); | |
295 | + x = String_new(); | |
296 | + String_assign(x, "abcdefghijklmnopqrstuvwxyz", NPOS); | |
297 | + assert(String_size(x) == 26); | |
298 | + assert(strcmp("abcdefghijklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
299 | + /* replace */ | |
300 | + String_replace(x, 0, 3, "ABC", NPOS); | |
301 | + assert(String_size(x) == 26); | |
302 | + assert(strcmp("ABCdefghijklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
303 | + String_replace(x, 6, 3, "GHI", NPOS); | |
304 | + assert(String_size(x) == 26); | |
305 | + assert(strcmp("ABCdefGHIjklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
306 | + String_replace(x, String_size(x)-3, NPOS, "XYZ", NPOS); | |
307 | + assert(String_size(x) == 26); | |
308 | + assert(strcmp("ABCdefGHIjklmnopqrstuvwXYZ", String_c_str(x)) == 0); | |
309 | + String_shrink(x, 0); | |
310 | + String_replace(x, 3, 0, "DEF", NPOS); | |
311 | + assert(String_size(x) == 29); | |
312 | + assert(strcmp("ABCDEFdefGHIjklmnopqrstuvwXYZ", String_c_str(x)) == 0); | |
313 | + String_replace(x, 6, 3, "", NPOS); | |
314 | + assert(String_size(x) == 26); | |
315 | + assert(strcmp("ABCDEFGHIjklmnopqrstuvwXYZ", String_c_str(x)) == 0); | |
316 | + String_replace(x, 0, 3, "hogehoge", 4); | |
317 | + assert(String_size(x) == 27); | |
318 | + assert(strcmp("hogeDEFGHIjklmnopqrstuvwXYZ", String_c_str(x)) == 0); | |
319 | + String_replace(x, 0, NPOS, "", NPOS); | |
320 | + assert(String_size(x) == 0); | |
321 | + assert(strcmp("", String_c_str(x)) == 0); | |
322 | + String_replace(x, 0, NPOS, "abc", NPOS); | |
323 | + assert(String_size(x) == 3); | |
324 | + assert(strcmp("abc", String_c_str(x)) == 0); | |
325 | + /* replace_c */ | |
326 | + String_assign(x, "abcdefghijklmnopqrstuvwxyz", NPOS); | |
327 | + assert(String_size(x) == 26); | |
328 | + assert(strcmp("abcdefghijklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
329 | + String_replace_c(x, 0, 3, 3, 'A'); | |
330 | + assert(String_size(x) == 26); | |
331 | + assert(strcmp("AAAdefghijklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
332 | + String_replace_c(x, 6, 3, 3, 'G'); | |
333 | + assert(String_size(x) == 26); | |
334 | + assert(strcmp("AAAdefGGGjklmnopqrstuvwxyz", String_c_str(x)) == 0); | |
335 | + String_replace_c(x, String_size(x)-3, NPOS, 3, 'X'); | |
336 | + assert(String_size(x) == 26); | |
337 | + assert(strcmp("AAAdefGGGjklmnopqrstuvwXXX", String_c_str(x)) == 0); | |
338 | + String_shrink(x, 0); | |
339 | + String_replace_c(x, 3, 0, 3, 'D'); | |
340 | + assert(String_size(x) == 29); | |
341 | + assert(strcmp("AAADDDdefGGGjklmnopqrstuvwXXX", String_c_str(x)) == 0); | |
342 | + String_replace_c(x, 6, 3, 0, 'E'); | |
343 | + assert(String_size(x) == 26); | |
344 | + assert(strcmp("AAADDDGGGjklmnopqrstuvwXXX", String_c_str(x)) == 0); | |
345 | + String_replace_c(x, 0, 3, 4, '0'); | |
346 | + assert(String_size(x) == 27); | |
347 | + assert(strcmp("0000DDDGGGjklmnopqrstuvwXXX", String_c_str(x)) == 0); | |
348 | + String_replace_c(x, 0, NPOS, 0, '0'); | |
349 | + assert(String_size(x) == 0); | |
350 | + assert(strcmp("", String_c_str(x)) == 0); | |
351 | + String_replace_c(x, 0, NPOS, 10, '0'); | |
352 | + assert(String_size(x) == 10); | |
353 | + assert(strcmp("0000000000", String_c_str(x)) == 0); | |
354 | + | |
355 | +#if 0 | |
356 | + string s = "abcdefghijklmnopqrstuvwxyz"; | |
357 | + s.replace(1, string::npos, "hoge"); | |
358 | + printf("%s\n", s.c_str()); | |
359 | +#endif | |
360 | + | |
361 | + String_delete(x); | |
362 | +} | |
363 | + | |
364 | +void print_find_test(const char *cstr, string &t, size_t i, size_t j, size_t k, size_t idx1, size_t idx2, const char *f) | |
365 | +{ | |
366 | + if (idx1 != idx2) { | |
367 | + if (k == NPOS) { | |
368 | + t.assign(cstr); | |
369 | + } else { | |
370 | + t.assign(cstr, k); | |
371 | + } | |
372 | + printf("cstr[%s]\ni[%3d], j[%3d], k[%3d], idx1[%3d], idx2[%3d] :%s\n", t.c_str(), i, j, k, idx1, idx2, f); | |
373 | + } | |
374 | +} | |
375 | + | |
376 | +void find_test(String *x, const string &s, size_t i, size_t j, size_t k, char *cstr) | |
377 | +{ | |
378 | + string t; | |
379 | + size_t idx1, idx2; | |
380 | + /* find */ | |
381 | + idx1 = String_find(String_c_str(x), &cstr[j], i, k); | |
382 | + idx2 = (k == NPOS) ? s.find(&cstr[j], i) : s.find(&cstr[j], i, k); | |
383 | + /* STLの実装によって動作が違うことがある */ | |
384 | + if (i == NPOS) { | |
385 | + assert(idx1 == NPOS); | |
386 | + } else { | |
387 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find"); | |
388 | + assert(idx1 == idx2); | |
389 | + } | |
390 | + /* find_c */ | |
391 | + idx1 = String_find_c(String_c_str(x), cstr[j], i); | |
392 | + idx2 = s.find(cstr[j], i); | |
393 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find_c"); | |
394 | + assert(idx1 == idx2); | |
395 | + assert(String_find_c(String_c_str(x), cstr[j], i) == String_find_first_of_c(String_c_str(x), cstr[j], i)); | |
396 | + | |
397 | + /* rfind */ | |
398 | + idx1 = String_rfind(String_c_str(x), &cstr[j], i, k); | |
399 | + idx2 = (k == NPOS) ? s.rfind(&cstr[j], i) : s.rfind(&cstr[j], i, k); | |
400 | + print_find_test(&cstr[j], t, i, j, k, idx2, idx2, "rfind"); | |
401 | + assert(idx1 == idx2); | |
402 | + /* rfind_c */ | |
403 | + idx1 = String_rfind_c(String_c_str(x), cstr[j], i); | |
404 | + idx2 = s.rfind(cstr[j], i); | |
405 | + print_find_test(&cstr[j], t, i, j, k, idx2, idx2, "rfind_c"); | |
406 | + assert(idx1 == idx2); | |
407 | + assert(String_rfind_c(String_c_str(x), cstr[j], i) == String_find_last_of_c(String_c_str(x), cstr[j], i)); | |
408 | + | |
409 | + /* find_first_of */ | |
410 | + idx1 = String_find_first_of(String_c_str(x), &cstr[j], i, k); | |
411 | + idx2 = (k == NPOS) ? s.find_first_of(&cstr[j], i) : s.find_first_of(&cstr[j], i, k); | |
412 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find_first_of"); | |
413 | + assert(idx1 == idx2); | |
414 | + /* find_first_of_c */ | |
415 | + idx1 = String_find_first_of_c(String_c_str(x), cstr[j], i); | |
416 | + idx2 = s.find_first_of(cstr[j], i); | |
417 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find_first_of_c"); | |
418 | + assert(idx1 == idx2); | |
419 | + | |
420 | + /* find_last_of */ | |
421 | + idx1 = String_find_last_of(String_c_str(x), &cstr[j], i, k); | |
422 | + idx2 = (k == NPOS) ? s.find_last_of(&cstr[j], i) : s.find_last_of(&cstr[j], i, k); | |
423 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find_last_of"); | |
424 | + assert(idx1 == idx2); | |
425 | + /* find_last_of_c */ | |
426 | + idx1 = String_find_last_of_c(String_c_str(x), cstr[j], i); | |
427 | + idx2 = s.find_last_of(cstr[j], i); | |
428 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find_last_of_c"); | |
429 | + assert(idx1 == idx2); | |
430 | + | |
431 | + /* find_first_not_of */ | |
432 | + idx1 = String_find_first_not_of(String_c_str(x), &cstr[j], i, k); | |
433 | + idx2 = (k == NPOS) ? s.find_first_not_of(&cstr[j], i) : s.find_first_not_of(&cstr[j], i, k); | |
434 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find_first_not_of"); | |
435 | + assert(idx1 == idx2); | |
436 | + /* find_first_not_of_c */ | |
437 | + idx1 = String_find_first_not_of_c(String_c_str(x), cstr[j], i); | |
438 | + idx2 = s.find_first_not_of(cstr[j], i); | |
439 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find_first_not_of_c"); | |
440 | + assert(idx1 == idx2); | |
441 | + | |
442 | + /* find_last_not_of */ | |
443 | + idx1 = String_find_last_not_of(String_c_str(x), &cstr[j], i, k); | |
444 | + idx2 = (k == NPOS) ? s.find_last_not_of(&cstr[j], i) : s.find_last_not_of(&cstr[j], i, k); | |
445 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find_last_not_of"); | |
446 | + assert(idx1 == idx2); | |
447 | + /* find_last_not_of_c */ | |
448 | + idx1 = String_find_last_not_of_c(String_c_str(x), cstr[j], i); | |
449 | + idx2 = s.find_last_not_of(cstr[j], i); | |
450 | + print_find_test(&cstr[j], t, i, j, k, idx1, idx2, "find_last_not_of_c"); | |
451 | + assert(idx1 == idx2); | |
452 | +} | |
453 | + | |
454 | +void StringTest_test_1_5(void) | |
455 | +{ | |
456 | + String *x; | |
457 | + String *y; | |
458 | + string s; | |
459 | + size_t i, j, k; | |
460 | + printf("***** test_1_5 *****\n"); | |
461 | + x = String_new_cstr("abc abcd abcde abcdef abcdefg abcdefgh abcdefghi", NPOS); | |
462 | + y = String_new_cstr("abcdefghijklmnopqrstuvwxyz", NPOS); | |
463 | + s = String_c_str(x); | |
464 | + assert(strcmp(s.c_str(), String_c_str(x)) == 0); | |
465 | + for (i = 0; i < String_size(x); i++) { | |
466 | + for (j = 0; j < String_size(x); j++) { | |
467 | + for (k = 0; k < String_size(x) -j +1; k++) { | |
468 | + find_test(x, s, i, j, k, String_c_str(x)); | |
469 | + } | |
470 | + if (k == String_size(x) -j +1) { | |
471 | + find_test(x, s, i, j, NPOS, String_c_str(x)); | |
472 | + } | |
473 | + if (j <= String_size(y)) { | |
474 | + for (k = 0; k < String_size(y) -j +1; k++) { | |
475 | + find_test(x, s, i, j, k, String_c_str(y)); | |
476 | + } | |
477 | + if (k == String_size(y) -j +1) { | |
478 | + find_test(x, s, i, j, NPOS, String_c_str(y)); | |
479 | + } | |
480 | + } | |
481 | + } | |
482 | + } | |
483 | + for (j = 0; j < String_size(x); j++) { | |
484 | + for (k = 0; k < String_size(x) -j +1; k++) { | |
485 | + find_test(x, s, NPOS, j, k, String_c_str(x)); | |
486 | + } | |
487 | + if (k == String_size(x) -j +1) { | |
488 | + find_test(x, s, NPOS, j, NPOS, String_c_str(x)); | |
489 | + } | |
490 | + if (j <= String_size(y)) { | |
491 | + for (k = 0; k < String_size(y) -j +1; k++) { | |
492 | + find_test(x, s, NPOS, j, k, String_c_str(y)); | |
493 | + } | |
494 | + if (k == String_size(y) -j +1) { | |
495 | + find_test(x, s, NPOS, j, NPOS, String_c_str(y)); | |
496 | + } | |
497 | + } | |
498 | + } | |
499 | + | |
500 | + String_delete(x); | |
501 | + String_delete(y); | |
502 | +} | |
503 | + | |
504 | + | |
505 | +void StringTest_run(void) | |
506 | +{ | |
507 | + printf("\n===== string test =====\n"); | |
508 | + StringTest_test_1_1(); | |
509 | + StringTest_test_1_2(); | |
510 | + StringTest_test_1_3(); | |
511 | + StringTest_test_1_4(); | |
512 | + StringTest_test_1_5(); | |
513 | +} | |
514 | + | |
515 | +char buf[1024*1024]; | |
516 | +Heap heap; | |
517 | + | |
518 | +int main(void) | |
519 | +{ | |
520 | +#ifdef MY_MALLOC | |
521 | + Heap_init(&heap, buf, sizeof buf); | |
522 | +#endif | |
523 | + StringTest_run(); | |
524 | +#ifdef MY_MALLOC | |
525 | + DUMP_MEMORY_LEAK(&heap, 0); | |
526 | +#endif | |
527 | + return 0; | |
528 | +} |
@@ -0,0 +1,379 @@ | ||
1 | +#include "test.h" | |
2 | + | |
3 | + | |
4 | +LIST_IMPLEMENT(UCharList, unsigned char) | |
5 | +LIST_IMPLEMENT(IntList, int) | |
6 | +LIST_IMPLEMENT(StrList, char *) | |
7 | +LIST_IMPLEMENT(HogeList, Hoge) | |
8 | + | |
9 | + | |
10 | +static HogeList *hl; | |
11 | + | |
12 | +#define NELEMS(array) (sizeof(array) / sizeof(array[0])) | |
13 | + | |
14 | +static Hoge hogetab[] = { | |
15 | + {"000", 0}, | |
16 | + {"001", 1}, | |
17 | + {"002", 2}, | |
18 | + {"003", 3}, | |
19 | + {"004", 4}, | |
20 | + {"005", 5}, | |
21 | + {"006", 6}, | |
22 | + {"007", 7}, | |
23 | + {"008", 8}, | |
24 | + {"009", 9}, | |
25 | + {"010", 10}, | |
26 | + {"011", 11}, | |
27 | + {"012", 12}, | |
28 | + {"013", 13}, | |
29 | + {"014", 14}, | |
30 | + {"015", 15}, | |
31 | + {"016", 16}, | |
32 | + {"017", 17}, | |
33 | + {"018", 18}, | |
34 | +}; | |
35 | + | |
36 | + | |
37 | + | |
38 | +void ListTest_test_1_1(void) | |
39 | +{ | |
40 | + Hoge hoge; | |
41 | + printf("***** test_1_1 *****\n"); | |
42 | + /* 初期状態 */ | |
43 | + assert(HogeList_size(hl) == 0); | |
44 | + assert(HogeList_empty(hl)); | |
45 | + assert(HogeList_begin(hl) == HogeList_end(hl)); | |
46 | + assert(HogeList_rbegin(hl) == HogeList_rend(hl)); | |
47 | + /* clear */ | |
48 | + hoge = hogetab[0]; | |
49 | + assert(HogeList_push_back(hl, hoge)); | |
50 | + assert(HogeList_push_back(hl, hoge)); | |
51 | + assert(HogeList_push_back(hl, hoge)); | |
52 | + HogeList_clear(hl); | |
53 | + assert(HogeList_size(hl) == 0); | |
54 | + assert(HogeList_empty(hl)); | |
55 | +} | |
56 | + | |
57 | +void ListTest_test_1_2(void) | |
58 | +{ | |
59 | + Hoge hoge; | |
60 | + int i; | |
61 | + printf("***** test_1_2 *****\n"); | |
62 | + /* push_back */ | |
63 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
64 | + assert(HogeList_push_back(hl, hogetab[i])); | |
65 | + } | |
66 | + assert(HogeList_size(hl) == NELEMS(hogetab)); | |
67 | + assert(!HogeList_empty(hl)); | |
68 | + /* pop_front */ | |
69 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
70 | + /* front */ | |
71 | + hoge = HogeList_front(hl); | |
72 | + assert(!strcmp(hoge.key, hogetab[i].key)); | |
73 | + assert(hoge.value == hogetab[i].value); | |
74 | + /* back */ | |
75 | + hoge = HogeList_back(hl); | |
76 | + assert(!strcmp(hoge.key, hogetab[NELEMS(hogetab)-1].key)); | |
77 | + assert(hoge.value == hogetab[NELEMS(hogetab)-1].value); | |
78 | + /* pop_front */ | |
79 | + hoge = HogeList_pop_front(hl); | |
80 | + assert(!strcmp(hoge.key, hogetab[i].key)); | |
81 | + assert(hoge.value == hogetab[i].value); | |
82 | + } | |
83 | + assert(HogeList_size(hl) == 0); | |
84 | + assert(HogeList_empty(hl)); | |
85 | + /* push_front */ | |
86 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
87 | + assert(HogeList_push_front(hl, hogetab[i])); | |
88 | + } | |
89 | + assert(HogeList_size(hl) == NELEMS(hogetab)); | |
90 | + assert(!HogeList_empty(hl)); | |
91 | + /* pop_back */ | |
92 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
93 | + /* front */ | |
94 | + hoge = HogeList_front(hl); | |
95 | + assert(!strcmp(hoge.key, hogetab[NELEMS(hogetab)-1].key)); | |
96 | + assert(hoge.value == hogetab[NELEMS(hogetab)-1].value); | |
97 | + /* back */ | |
98 | + hoge = HogeList_back(hl); | |
99 | + assert(!strcmp(hoge.key, hogetab[i].key)); | |
100 | + assert(hoge.value == hogetab[i].value); | |
101 | + /* pop_back */ | |
102 | + hoge = HogeList_pop_back(hl); | |
103 | + assert(!strcmp(hoge.key, hogetab[i].key)); | |
104 | + assert(hoge.value == hogetab[i].value); | |
105 | + } | |
106 | + assert(HogeList_size(hl) == 0); | |
107 | + assert(HogeList_empty(hl)); | |
108 | +} | |
109 | + | |
110 | +void ListTest_test_1_3(void) | |
111 | +{ | |
112 | + Hoge hoge; | |
113 | + int c = 0; | |
114 | + printf("***** test_1_3 *****\n"); | |
115 | + /* 大量にpush_back */ | |
116 | + hoge = hogetab[0]; | |
117 | + while (c < 1000000 && HogeList_push_back(hl, hoge)) { | |
118 | + c++; | |
119 | + } | |
120 | +/* printf("size: %d, c: %d\n", HogeList_size(hl), c);*/ | |
121 | + assert(HogeList_size(hl) == c); | |
122 | + assert(!HogeList_empty(hl)); | |
123 | + /* 大量にpush_front */ | |
124 | + HogeList_clear(hl); | |
125 | + assert(HogeList_size(hl) == 0); | |
126 | + assert(HogeList_empty(hl)); | |
127 | + c = 0; | |
128 | + while (c < 1000000 && HogeList_push_front(hl, hoge)) { | |
129 | + c++; | |
130 | + } | |
131 | +/* printf("size: %d, c: %d\n", HogeList_size(hl), c);*/ | |
132 | + assert(HogeList_size(hl) == c); | |
133 | + assert(!HogeList_empty(hl)); | |
134 | + HogeList_clear(hl); | |
135 | + assert(HogeList_size(hl) == 0); | |
136 | + assert(HogeList_empty(hl)); | |
137 | +} | |
138 | + | |
139 | +void ListTest_test_1_4(void) | |
140 | +{ | |
141 | + Hoge hoge; | |
142 | + int i; | |
143 | + HogeListIterator pos; | |
144 | + printf("***** test_1_4 *****\n"); | |
145 | + /* push_back */ | |
146 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
147 | + assert(HogeList_push_back(hl, hogetab[i])); | |
148 | + } | |
149 | + assert(HogeList_size(hl) == NELEMS(hogetab)); | |
150 | + assert(!HogeList_empty(hl)); | |
151 | + /* at */ | |
152 | + for (i = 0, pos = HogeList_begin(hl); pos != HogeList_end(hl); pos = HogeList_next(pos), i++) { | |
153 | + hoge = *HogeList_at(pos); | |
154 | + assert(!strcmp(hoge.key, hogetab[i].key)); | |
155 | + assert(hoge.value == hogetab[i].value); | |
156 | + } | |
157 | + assert(i == NELEMS(hogetab)); | |
158 | + for (i = 0, pos = HogeList_begin(hl); pos != HogeList_end(hl); pos = HogeList_next(pos), i++) { | |
159 | + *HogeList_at(pos) = hogetab[0]; | |
160 | + } | |
161 | + assert(i == NELEMS(hogetab)); | |
162 | + for (pos = HogeList_begin(hl); pos != HogeList_end(hl); pos = HogeList_next(pos)) { | |
163 | + hoge = *HogeList_at(pos); | |
164 | + assert(!strcmp(hoge.key, hogetab[0].key)); | |
165 | + assert(hoge.value == hogetab[0].value); | |
166 | + } | |
167 | + while (!HogeList_empty(hl)) { | |
168 | + HogeList_pop_front(hl); | |
169 | + } | |
170 | + assert(HogeList_size(hl) == 0); | |
171 | +} | |
172 | + | |
173 | +void ListTest_test_1_5(void) | |
174 | +{ | |
175 | + Hoge hoge; | |
176 | + int i; | |
177 | + int flag = 0; | |
178 | + HogeListIterator pos; | |
179 | + printf("***** test_1_5 *****\n"); | |
180 | + /* beginの位置にinsert */ | |
181 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
182 | + assert(HogeList_insert(hl, HogeList_begin(hl), hogetab[i]) == HogeList_begin(hl)); | |
183 | + } | |
184 | + HogeList_clear(hl); | |
185 | + /* endの位置にinsert */ | |
186 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
187 | + assert(HogeList_insert(hl, HogeList_end(hl), hogetab[i]) == HogeList_rbegin(hl)); | |
188 | + } | |
189 | + assert(HogeList_size(hl) == NELEMS(hogetab)); | |
190 | + assert(!HogeList_empty(hl)); | |
191 | + /* 真ん中の位置にinsert */ | |
192 | + for (i = 0, pos = HogeList_begin(hl); pos != HogeList_end(hl); pos = HogeList_next(pos), i++) { | |
193 | + hoge = *HogeList_at(pos); | |
194 | + assert(!strcmp(hoge.key, hogetab[i].key)); | |
195 | + assert(hoge.value == hogetab[i].value); | |
196 | + if (i == NELEMS(hogetab)/2) { | |
197 | + hoge = hogetab[0]; | |
198 | + assert(HogeList_insert(hl, pos, hoge) == HogeList_prev(pos)); | |
199 | + break; | |
200 | + } | |
201 | + } | |
202 | + assert(HogeList_size(hl) == NELEMS(hogetab)+1); | |
203 | + for (i = 0, pos = HogeList_begin(hl); pos != HogeList_end(hl); pos = HogeList_next(pos), i++) { | |
204 | + hoge = *HogeList_at(pos); | |
205 | + if (!flag && i == NELEMS(hogetab)/2) { | |
206 | + assert(!strcmp(hoge.key, hogetab[0].key)); | |
207 | + assert(hoge.value == hogetab[0].value); | |
208 | + flag = 1; | |
209 | + i--; | |
210 | + } else { | |
211 | + assert(!strcmp(hoge.key, hogetab[i].key)); | |
212 | + assert(hoge.value == hogetab[i].value); | |
213 | + } | |
214 | + } | |
215 | + HogeList_clear(hl); | |
216 | +} | |
217 | + | |
218 | +void ListTest_test_1_6(void) | |
219 | +{ | |
220 | + Hoge hoge; | |
221 | + int i; | |
222 | + HogeListIterator pos; | |
223 | + size_t size; | |
224 | + printf("***** test_1_6 *****\n"); | |
225 | + /* push_back */ | |
226 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
227 | + assert(HogeList_push_back(hl, hogetab[i])); | |
228 | + } | |
229 | + assert(HogeList_size(hl) == NELEMS(hogetab)); | |
230 | + assert(!HogeList_empty(hl)); | |
231 | + /* beginの位置の要素をerase */ | |
232 | + size = HogeList_size(hl); | |
233 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
234 | + pos = HogeList_begin(hl); | |
235 | + assert(HogeList_next(pos) == HogeList_erase(hl, pos)); | |
236 | + assert(HogeList_size(hl) == --size); | |
237 | + } | |
238 | + assert(HogeList_size(hl) == 0); | |
239 | + assert(HogeList_empty(hl)); | |
240 | + /* push_back */ | |
241 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
242 | + assert(HogeList_push_back(hl, hogetab[i])); | |
243 | + } | |
244 | + assert(HogeList_size(hl) == NELEMS(hogetab)); | |
245 | + assert(!HogeList_empty(hl)); | |
246 | + /* endの前の位置の要素をerase */ | |
247 | + size = HogeList_size(hl); | |
248 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
249 | + pos = HogeList_rbegin(hl); | |
250 | + assert(HogeList_next(pos) == HogeList_erase(hl, pos)); | |
251 | + assert(HogeList_size(hl) == --size); | |
252 | + } | |
253 | + assert(HogeList_size(hl) == 0); | |
254 | + assert(HogeList_empty(hl)); | |
255 | + /* push_back */ | |
256 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
257 | + assert(HogeList_push_back(hl, hogetab[i])); | |
258 | + } | |
259 | + assert(HogeList_size(hl) == NELEMS(hogetab)); | |
260 | + assert(!HogeList_empty(hl)); | |
261 | + /* 真ん中の位置の要素をerase */ | |
262 | + for (i = 0, pos = HogeList_begin(hl); pos != HogeList_end(hl); i++) { | |
263 | + if (i == NELEMS(hogetab)/2) { | |
264 | + pos = HogeList_erase(hl, pos); | |
265 | + } else { | |
266 | + pos = HogeList_next(pos); | |
267 | + } | |
268 | + } | |
269 | + assert(HogeList_size(hl) == NELEMS(hogetab)-1); | |
270 | + for (i = 0, pos = HogeList_begin(hl); pos != HogeList_end(hl); pos = HogeList_next(pos), i++) { | |
271 | + hoge = *HogeList_at(pos); | |
272 | + if (i >= NELEMS(hogetab)/2) { | |
273 | + assert(!strcmp(hoge.key, hogetab[i+1].key)); | |
274 | + assert(hoge.value == hogetab[i+1].value); | |
275 | + } else { | |
276 | + assert(!strcmp(hoge.key, hogetab[i].key)); | |
277 | + assert(hoge.value == hogetab[i].value); | |
278 | + } | |
279 | + } | |
280 | + /* erase_range */ | |
281 | + assert(!HogeList_empty(hl)); | |
282 | + assert(HogeList_end(hl) == HogeList_erase_range(hl, HogeList_begin(hl), HogeList_end(hl))); | |
283 | + assert(HogeList_empty(hl)); | |
284 | +} | |
285 | + | |
286 | +void ListTest_test_1_7(void) | |
287 | +{ | |
288 | + Hoge hoge; | |
289 | + int i; | |
290 | + HogeListIterator pos; | |
291 | + printf("***** test_1_7 *****\n"); | |
292 | + /* push_back */ | |
293 | + for (i = 0; i < NELEMS(hogetab); i++) { | |
294 | + assert(HogeList_push_back(hl, hogetab[i])); | |
295 | + } | |
296 | + assert(HogeList_size(hl) == NELEMS(hogetab)); | |
297 | + assert(!HogeList_empty(hl)); | |
298 | + /* rbegin/rend 逆順に走査 */ | |
299 | + for (i = 0, pos = HogeList_rbegin(hl); pos != HogeList_rend(hl); pos = HogeList_prev(pos), i++) { | |
300 | + hoge = *HogeList_at(pos); | |
301 | + assert(!strcmp(hoge.key, hogetab[NELEMS(hogetab)-1 - i].key)); | |
302 | + assert(hoge.value == hogetab[NELEMS(hogetab)-1 - i].value); | |
303 | + } | |
304 | + assert(i == NELEMS(hogetab)); | |
305 | + assert(HogeList_next(HogeList_rbegin(hl)) == HogeList_end(hl)); | |
306 | + assert(HogeList_prev(HogeList_begin(hl)) == HogeList_rend(hl)); | |
307 | + HogeList_clear(hl); | |
308 | +} | |
309 | + | |
310 | + | |
311 | +void ListTest_test_2_1(void) | |
312 | +{ | |
313 | + IntList *il = IntList_new(); | |
314 | + IntList *x; | |
315 | + IntListIterator pos; | |
316 | + IntListIterator pos2; | |
317 | + int buf[32]; | |
318 | + int i; | |
319 | + printf("***** test_2_1 *****\n"); | |
320 | + for (i = 0; i < 32; i++) buf[i] = i; | |
321 | + /* assign */ | |
322 | + assert(IntList_size(il) == 0); | |
323 | + assert(IntList_assign(il, buf, 32)); | |
324 | + assert(IntList_size(il) == 32); | |
325 | + for (pos = IntList_begin(il), i = 0; pos != IntList_end(il); pos = IntList_next(pos), i++) { | |
326 | + assert(*IntList_at(pos) == i); | |
327 | + } | |
328 | + /* resize */ | |
329 | + assert(IntList_resize(il, 64, 100)); | |
330 | + assert(IntList_size(il) == 64); | |
331 | + for (pos = IntList_begin(il), i = 0; pos != IntList_end(il); pos = IntList_next(pos), i++) { | |
332 | + if (i < 32) { | |
333 | + assert(*IntList_at(pos) == i); | |
334 | + } else { | |
335 | + assert(*IntList_at(pos) == 100); | |
336 | + } | |
337 | + } | |
338 | + assert(IntList_resize(il, 16, 99)); | |
339 | + assert(IntList_size(il) == 16); | |
340 | + for (pos = IntList_begin(il), i = 0; pos != IntList_end(il); pos = IntList_next(pos), i++) { | |
341 | + assert(*IntList_at(pos) == i); | |
342 | + } | |
343 | + assert(IntList_resize(il, 0, 99)); | |
344 | + assert(IntList_size(il) == 0); | |
345 | + assert(IntList_resize(il, 100, 99)); | |
346 | + /* new_copy */ | |
347 | + x = IntList_new_copy(il); | |
348 | + assert(IntList_size(x) == IntList_size(il)); | |
349 | + pos2 = IntList_begin(x); | |
350 | + for (pos = IntList_begin(il); pos != IntList_end(il); pos = IntList_next(pos)) { | |
351 | + assert(*IntList_at(pos) == *IntList_at(pos2)); | |
352 | + pos2 = IntList_next(pos2); | |
353 | + } | |
354 | + | |
355 | + IntList_delete(il); | |
356 | + IntList_delete(x); | |
357 | +} | |
358 | + | |
359 | + | |
360 | + | |
361 | +void ListTest_run(void) | |
362 | +{ | |
363 | + printf("\n===== list test =====\n"); | |
364 | + hl = HogeList_new(); | |
365 | + assert(hl); | |
366 | + | |
367 | + ListTest_test_1_1(); | |
368 | + ListTest_test_1_2(); | |
369 | + ListTest_test_1_3(); | |
370 | + ListTest_test_1_4(); | |
371 | + ListTest_test_1_5(); | |
372 | + ListTest_test_1_6(); | |
373 | + ListTest_test_1_7(); | |
374 | + ListTest_test_2_1(); | |
375 | + | |
376 | + HogeList_delete(hl); | |
377 | +} | |
378 | + | |
379 | + |
@@ -0,0 +1,784 @@ | ||
1 | +#include "test.h" | |
2 | + | |
3 | +#include <string.h> | |
4 | +#include <time.h> | |
5 | + | |
6 | +/* int */ | |
7 | +SET_IMPLEMENT(IntSetA, int, SIMPLE_CMP, ASC) | |
8 | +SET_DEBUG_IMPLEMENT(IntSetA, int, SIMPLE_CMP, ASC, %d, VISUAL) | |
9 | +static IntSetA *ia; | |
10 | + | |
11 | +SET_IMPLEMENT(IntSetD, int, SIMPLE_CMP, DESC) | |
12 | +SET_DEBUG_IMPLEMENT(IntSetD, int, SIMPLE_CMP, DESC, %d, VISUAL) | |
13 | +static IntSetD *id; | |
14 | + | |
15 | +MULTISET_IMPLEMENT(IntMSetA, int, SIMPLE_CMP, ASC) | |
16 | +SET_DEBUG_IMPLEMENT(IntMSetA, int, SIMPLE_CMP, ASC, %d, VISUAL) | |
17 | +static IntMSetA *ima; | |
18 | + | |
19 | + | |
20 | +/* double */ | |
21 | +SET_IMPLEMENT(DoubleSetA, double, SIMPLE_CMP, ASC) | |
22 | +SET_DEBUG_IMPLEMENT(DoubleSetA, double, SIMPLE_CMP, ASC, %g, VISUAL) | |
23 | +static DoubleSetA *da; | |
24 | + | |
25 | + | |
26 | +/* ptr */ | |
27 | +SET_IMPLEMENT(PtrSetA, int*, SIMPLE_CMP, ASC) | |
28 | +SET_DEBUG_IMPLEMENT(PtrSetA, int*, SIMPLE_CMP, ASC, %p, VISUAL) | |
29 | +static PtrSetA *pa; | |
30 | + | |
31 | + | |
32 | +/* str */ | |
33 | +SET_IMPLEMENT(StrSetA, char*, strcmp, ASC) | |
34 | +SET_DEBUG_IMPLEMENT(StrSetA, char*, strcmp, ASC, %s, VISUAL) | |
35 | +static StrSetA *sa; | |
36 | + | |
37 | + | |
38 | + | |
39 | +#define SIZE 32 | |
40 | +static int hoge_int[SIZE]; | |
41 | +static double hoge_double[SIZE]; | |
42 | +static int *hoge_ptr[SIZE]; | |
43 | +static char *hoge_str[SIZE]; | |
44 | +static char str[SIZE][16]; | |
45 | + | |
46 | +void set_init_hoge(void) | |
47 | +{ | |
48 | + int i; | |
49 | + int tmp; | |
50 | + IntDeque *q = IntDeque_new(SIZE/2); | |
51 | + srand(time(0)); | |
52 | +/* printf("hoge data\n");*/ | |
53 | + for (i = 0; i < SIZE/2; i++) { | |
54 | + IntDeque_push_back(q, i); | |
55 | + } | |
56 | + for (i = 0; i < SIZE; i++) { | |
57 | + if (!IntDeque_empty(q)) { | |
58 | + int rnd = rand() % IntDeque_size(q); | |
59 | + tmp = *IntDeque_at(q, rnd); | |
60 | + IntDeque_erase(q, rnd); | |
61 | + } else { | |
62 | + tmp = i/2; | |
63 | + } | |
64 | + hoge_int[i] = tmp; | |
65 | + hoge_double[i] = hoge_int[i] * 0.5; | |
66 | + hoge_ptr[i] = &hoge_int[tmp]; | |
67 | + sprintf(str[i], "%05d", i < SIZE/2 ? i : tmp); | |
68 | + hoge_str[i] = str[i]; | |
69 | +/* printf("%4d: int[%3d], double[%5g], ptr[%p], str[%s]\n",*/ | |
70 | +/* i, hoge_int[i], hoge_double[i], hoge_ptr[i], hoge_str[i]);*/ | |
71 | + } | |
72 | + IntDeque_delete(q); | |
73 | +} | |
74 | + | |
75 | +void SetTest_test_1_1(void) | |
76 | +{ | |
77 | + int i; | |
78 | + size_t count = 0; | |
79 | + int success[SIZE]; | |
80 | + IntSetAIterator pos[SIZE]; | |
81 | + IntSetAIterator p; | |
82 | + printf("***** test_1_1 *****\n"); | |
83 | + ia = IntSetA_new(); | |
84 | + /* 初期状態 */ | |
85 | + assert(IntSetA_empty(ia)); | |
86 | + assert(IntSetA_size(ia) == 0); | |
87 | + assert(IntSetA_begin(ia) == IntSetA_end(ia)); | |
88 | + assert(IntSetA_rbegin(ia) == IntSetA_rend(ia)); | |
89 | + /* insert */ | |
90 | + for (i = 0; i < SIZE; i++) { | |
91 | + pos[i] = IntSetA_insert(ia, hoge_int[i], &success[i]); | |
92 | + if (i < SIZE/2) { | |
93 | + assert(success[i]); | |
94 | + count++; | |
95 | + } else { | |
96 | + assert(!success[i]); | |
97 | + } | |
98 | + assert(pos[i]); | |
99 | + } | |
100 | +/* IntSetA_print(ia);*/ | |
101 | + assert(!IntSetA_empty(ia)); | |
102 | + assert(IntSetA_size(ia) == count); | |
103 | + assert(count == SIZE/2); | |
104 | + /* count, find, lower_bound, upper_bound */ | |
105 | + for (i = 0; i < SIZE/2; i++) { | |
106 | + assert(IntSetA_count(ia, hoge_int[i]) == 1); | |
107 | + assert(pos[i] == IntSetA_find(ia, hoge_int[i])); | |
108 | + assert(pos[i] == IntSetA_lower_bound(ia, hoge_int[i])); | |
109 | + assert(pos[i] == IntSetA_upper_bound(ia, hoge_int[i]-1)); | |
110 | + assert(IntSetA_lower_bound(ia, hoge_int[i]+1) == IntSetA_upper_bound(ia, hoge_int[i])); | |
111 | + } | |
112 | + assert(IntSetA_find(ia, IntSetA_key(IntSetA_begin(ia)) -1) == IntSetA_end(ia)); | |
113 | + assert(IntSetA_lower_bound(ia, IntSetA_key(IntSetA_rbegin(ia)) +1) == IntSetA_end(ia)); | |
114 | + assert(IntSetA_upper_bound(ia, IntSetA_key(IntSetA_rbegin(ia))) == IntSetA_end(ia)); | |
115 | + /* begin, end, next, key */ | |
116 | + for (p = IntSetA_begin(ia), i = 0; p != IntSetA_end(ia); p = IntSetA_next(p), i++) { | |
117 | + assert(IntSetA_key(p) == i); | |
118 | + } | |
119 | + assert(i == SIZE/2); | |
120 | + assert(IntSetA_next(IntSetA_rbegin(ia)) == IntSetA_end(ia)); | |
121 | + /* rbegin, rend, prev, key */ | |
122 | + for (p = IntSetA_rbegin(ia), i = SIZE/2 -1; p != IntSetA_rend(ia); p = IntSetA_prev(p), i--) { | |
123 | + assert(IntSetA_key(p) == i); | |
124 | + } | |
125 | + assert(i == -1); | |
126 | + assert(IntSetA_prev(IntSetA_begin(ia)) == IntSetA_rend(ia)); | |
127 | + /* erase */ | |
128 | + for (i = 0; i < SIZE; i++) { | |
129 | + if (pos[i] && success[i]) { | |
130 | + IntSetAIterator itr = IntSetA_next(pos[i]); | |
131 | + assert(itr == IntSetA_erase(ia, pos[i])); | |
132 | + count--; | |
133 | + } | |
134 | + } | |
135 | + assert(IntSetA_empty(ia)); | |
136 | + assert(IntSetA_size(ia) == 0); | |
137 | + assert(count == 0); | |
138 | + /* erase_range */ | |
139 | + for (i = 0; i < SIZE/2; i++) { | |
140 | + pos[i] = IntSetA_insert(ia, hoge_int[i], NULL); | |
141 | + assert(pos[i]); | |
142 | + } | |
143 | + assert(IntSetA_size(ia) == SIZE/2); | |
144 | + assert(IntSetA_find(ia, SIZE/2 -2) == IntSetA_erase_range(ia, IntSetA_find(ia, 2), IntSetA_find(ia, SIZE/2 -2))); | |
145 | + assert(IntSetA_size(ia) == 4); | |
146 | + assert(IntSetA_end(ia) == IntSetA_erase_range(ia, IntSetA_begin(ia), IntSetA_end(ia))); | |
147 | + assert(IntSetA_size(ia) == 0); | |
148 | + assert(IntSetA_insert(ia, hoge_int[0], NULL)); | |
149 | + assert(IntSetA_size(ia) == 1); | |
150 | + assert(IntSetA_next(IntSetA_begin(ia)) == IntSetA_erase_range(ia, IntSetA_begin(ia), IntSetA_next(IntSetA_begin(ia)))); | |
151 | + assert(IntSetA_size(ia) == 0); | |
152 | + assert(IntSetA_insert(ia, 100, NULL)); | |
153 | + assert(IntSetA_insert(ia, 110, NULL)); | |
154 | + assert(IntSetA_size(ia) == 2); | |
155 | + assert(IntSetA_upper_bound(ia, 110) == IntSetA_erase_range(ia, IntSetA_lower_bound(ia, 100), IntSetA_upper_bound(ia, 110))); | |
156 | + assert(IntSetA_size(ia) == 0); | |
157 | + /* erase_key */ | |
158 | + for (i = 0; i < SIZE/2; i++) { | |
159 | + pos[i] = IntSetA_insert(ia, hoge_int[i], NULL); | |
160 | + assert(pos[i]); | |
161 | + } | |
162 | + assert(IntSetA_size(ia) == SIZE/2); | |
163 | + for (i = 0; i < SIZE/2; i++) { | |
164 | + assert(IntSetA_erase_key(ia, hoge_int[i]) == 1); | |
165 | + } | |
166 | + assert(IntSetA_size(ia) == 0); | |
167 | + /* 大量にinsert */ | |
168 | + count = 0; | |
169 | + while (count < 1000000 && IntSetA_insert(ia, count, NULL)) { | |
170 | + count++; | |
171 | + } | |
172 | + assert(IntSetA_size(ia) == count); | |
173 | + printf("count: %d\n", count); | |
174 | + printf("size: %d\n", IntSetA_size(ia)); | |
175 | + /* clear */ | |
176 | + IntSetA_clear(ia); | |
177 | + printf("size: %d\n", IntSetA_size(ia)); | |
178 | + assert(IntSetA_size(ia) == 0); | |
179 | + assert(IntSetA_insert(ia, 100, NULL)); | |
180 | + assert(IntSetA_size(ia) == 1); | |
181 | + IntSetA_clear(ia); | |
182 | + assert(IntSetA_size(ia) == 0); | |
183 | + IntSetA_clear(ia); | |
184 | + assert(IntSetA_size(ia) == 0); | |
185 | + | |
186 | + IntSetA_delete(ia); | |
187 | +} | |
188 | + | |
189 | +void SetTest_test_1_2(void) | |
190 | +{ | |
191 | + int i; | |
192 | + int success[SIZE]; | |
193 | + size_t count = 0; | |
194 | + IntSetDIterator pos[SIZE]; | |
195 | + IntSetDIterator p; | |
196 | + printf("***** test_1_2 *****\n"); | |
197 | + id = IntSetD_new(); | |
198 | + /* 初期状態 */ | |
199 | + assert(IntSetD_empty(id)); | |
200 | + assert(IntSetD_size(id) == 0); | |
201 | + assert(IntSetD_begin(id) == IntSetD_end(id)); | |
202 | + assert(IntSetD_rbegin(id) == IntSetD_rend(id)); | |
203 | + /* insert */ | |
204 | + for (i = 0; i < SIZE; i++) { | |
205 | + pos[i] = IntSetD_insert(id, hoge_int[i], &success[i]); | |
206 | + if (i < SIZE/2) { | |
207 | + assert(success[i]); | |
208 | + count++; | |
209 | + } else { | |
210 | + assert(!success[i]); | |
211 | + } | |
212 | + assert(pos[i]); | |
213 | + } | |
214 | +/* IntSetD_print(id);*/ | |
215 | + assert(!IntSetD_empty(id)); | |
216 | + assert(IntSetD_size(id) == count); | |
217 | + assert(count == SIZE/2); | |
218 | + /* count, find, lower_bound, upper_bound */ | |
219 | + for (i = 0; i < SIZE/2; i++) { | |
220 | + assert(IntSetD_count(id, hoge_int[i]) == 1); | |
221 | + assert(pos[i] == IntSetD_find(id, hoge_int[i])); | |
222 | + assert(pos[i] == IntSetD_lower_bound(id, hoge_int[i])); | |
223 | + assert(pos[i] == IntSetD_upper_bound(id, hoge_int[i]+1)); | |
224 | + assert(IntSetD_lower_bound(id, hoge_int[i]-1) == IntSetD_upper_bound(id, hoge_int[i])); | |
225 | + } | |
226 | + assert(IntSetD_find(id, IntSetD_key(IntSetD_begin(id)) +1) == IntSetD_end(id)); | |
227 | + assert(IntSetD_lower_bound(id, IntSetD_key(IntSetD_rbegin(id)) -1) == IntSetD_end(id)); | |
228 | + assert(IntSetD_upper_bound(id, IntSetD_key(IntSetD_rbegin(id))) == IntSetD_end(id)); | |
229 | + /* begin, end, next, key */ | |
230 | + for (p = IntSetD_begin(id), i = SIZE/2 -1; p != IntSetD_end(id); p = IntSetD_next(p), i--) { | |
231 | + assert(IntSetD_key(p) == i); | |
232 | + } | |
233 | + assert(i == -1); | |
234 | + assert(IntSetD_next(IntSetD_rbegin(id)) == IntSetD_end(id)); | |
235 | + /* rbegin, rend, prev, key */ | |
236 | + for (p = IntSetD_rbegin(id), i = 0; p != IntSetD_rend(id); p = IntSetD_prev(p), i++) { | |
237 | + assert(IntSetD_key(p) == i); | |
238 | + } | |
239 | + assert(i == SIZE/2); | |
240 | + assert(IntSetD_prev(IntSetD_begin(id)) == IntSetD_rend(id)); | |
241 | + /* erase */ | |
242 | + for (i = 0; i < SIZE; i++) { | |
243 | + if (pos[i] && success[i]) { | |
244 | + IntSetDIterator itr = IntSetD_next(pos[i]); | |
245 | + assert(itr == IntSetD_erase(id, pos[i])); | |
246 | + count--; | |
247 | + } | |
248 | + } | |
249 | + assert(IntSetD_empty(id)); | |
250 | + assert(IntSetD_size(id) == 0); | |
251 | + assert(count == 0); | |
252 | + /* erase_range */ | |
253 | + for (i = 0; i < SIZE/2; i++) { | |
254 | + pos[i] = IntSetD_insert(id, hoge_int[i], NULL); | |
255 | + assert(pos[i]); | |
256 | + } | |
257 | + assert(IntSetD_size(id) == SIZE/2); | |
258 | + assert(IntSetD_find(id, 1) == IntSetD_erase_range(id, IntSetD_find(id, SIZE/2-1 -2), IntSetD_find(id, 1))); | |
259 | + assert(IntSetD_size(id) == 4); | |
260 | + assert(IntSetD_end(id) == IntSetD_erase_range(id, IntSetD_begin(id), IntSetD_end(id))); | |
261 | + assert(IntSetD_size(id) == 0); | |
262 | + assert(IntSetD_insert(id, hoge_int[0], NULL)); | |
263 | + assert(IntSetD_size(id) == 1); | |
264 | + assert(IntSetD_next(IntSetD_begin(id)) == IntSetD_erase_range(id, IntSetD_begin(id), IntSetD_next(IntSetD_begin(id)))); | |
265 | + assert(IntSetD_size(id) == 0); | |
266 | + assert(IntSetD_insert(id, 100, NULL)); | |
267 | + assert(IntSetD_insert(id, 110, NULL)); | |
268 | + assert(IntSetD_size(id) == 2); | |
269 | + assert(IntSetD_upper_bound(id, 100) == IntSetD_erase_range(id, IntSetD_lower_bound(id, 110), IntSetD_upper_bound(id, 100))); | |
270 | + assert(IntSetD_size(id) == 0); | |
271 | + /* erase_key */ | |
272 | + for (i = 0; i < SIZE/2; i++) { | |
273 | + pos[i] = IntSetD_insert(id, hoge_int[i], NULL); | |
274 | + assert(pos[i]); | |
275 | + } | |
276 | + assert(IntSetD_size(id) == SIZE/2); | |
277 | + for (i = 0; i < SIZE/2; i++) { | |
278 | + assert(IntSetD_erase_key(id, hoge_int[i]) == 1); | |
279 | + } | |
280 | + assert(IntSetD_size(id) == 0); | |
281 | + /* 大量にinsert */ | |
282 | + count = 0; | |
283 | + while (count < 1000000 && IntSetD_insert(id, count, NULL)) { | |
284 | + count++; | |
285 | + } | |
286 | + assert(IntSetD_size(id) == count); | |
287 | + printf("count: %d\n", count); | |
288 | + | |
289 | + IntSetD_delete(id); | |
290 | +} | |
291 | + | |
292 | +void SetTest_test_1_3(void) | |
293 | +{ | |
294 | + int i; | |
295 | + size_t count = 0; | |
296 | + IntMSetAIterator pos[SIZE]; | |
297 | + IntMSetAIterator p; | |
298 | + int flag[SIZE/2] = {0}; | |
299 | + printf("***** test_1_3 *****\n"); | |
300 | + ima = IntMSetA_new(); | |
301 | + /* 初期状態 */ | |
302 | + assert(IntMSetA_empty(ima)); | |
303 | + assert(IntMSetA_size(ima) == 0); | |
304 | + assert(IntMSetA_begin(ima) == IntMSetA_end(ima)); | |
305 | + assert(IntMSetA_rbegin(ima) == IntMSetA_rend(ima)); | |
306 | + /* insert */ | |
307 | + for (i = 0; i < SIZE; i++) { | |
308 | + pos[i] = IntMSetA_insert(ima, hoge_int[i]); | |
309 | + assert(pos[i] && pos[i] != IntMSetA_end(ima)); | |
310 | + count++; | |
311 | + } | |
312 | +/* IntMSetA_print(ima);*/ | |
313 | + assert(!IntMSetA_empty(ima)); | |
314 | + assert(IntMSetA_size(ima) == count); | |
315 | + assert(count == SIZE); | |
316 | + /* count */ | |
317 | + for (i = 0; i < SIZE; i++) { | |
318 | + if (i < SIZE/2/2) { | |
319 | + assert(IntMSetA_count(ima, i) == 1); | |
320 | + } else if (i < SIZE/2) { | |
321 | + assert(IntMSetA_count(ima, i) == 3); | |
322 | + } else { | |
323 | + assert(IntMSetA_count(ima, i) == 0); | |
324 | + } | |
325 | + } | |
326 | + /* find, lower_bound, upper_bound */ | |
327 | + for (i = 0; i < SIZE; i++) { | |
328 | + if (IntMSetA_count(ima, hoge_int[i]) == 1) { | |
329 | + assert(pos[i] == IntMSetA_find(ima, hoge_int[i])); | |
330 | + assert(pos[i] == IntMSetA_lower_bound(ima, hoge_int[i])); | |
331 | + assert(pos[i] == IntMSetA_upper_bound(ima, hoge_int[i]-1)); | |
332 | + } else if (IntMSetA_count(ima, hoge_int[i]) == 3) { | |
333 | + if (!flag[hoge_int[i]]) { | |
334 | + flag[hoge_int[i]] = 1; | |
335 | + assert(pos[i] == IntMSetA_lower_bound(ima, hoge_int[i])); | |
336 | + assert(pos[i] == IntMSetA_upper_bound(ima, hoge_int[i]-1)); | |
337 | + } | |
338 | + } else { | |
339 | + assert(0); | |
340 | + } | |
341 | + assert(IntMSetA_lower_bound(ima, hoge_int[i]+1) == IntMSetA_upper_bound(ima, hoge_int[i])); | |
342 | + } | |
343 | + assert(IntMSetA_find(ima, IntMSetA_key(IntMSetA_begin(ima)) -1) == IntMSetA_end(ima)); | |
344 | + assert(IntMSetA_lower_bound(ima, IntMSetA_key(IntMSetA_rbegin(ima)) +1) == IntMSetA_end(ima)); | |
345 | + assert(IntMSetA_upper_bound(ima, IntMSetA_key(IntMSetA_rbegin(ima))) == IntMSetA_end(ima)); | |
346 | + /* begin, end, next, key */ | |
347 | + for (p = IntMSetA_begin(ima), i = 0; p != IntMSetA_end(ima); p = IntMSetA_next(p), i++) { | |
348 | +/* printf("%d, %d\n", i, IntMSetA_key(p));*/ | |
349 | + } | |
350 | + assert(i == SIZE); | |
351 | + assert(IntMSetA_next(IntMSetA_rbegin(ima)) == IntMSetA_end(ima)); | |
352 | + /* rbegin, rend, prev, key */ | |
353 | + for (p = IntMSetA_rbegin(ima), i = SIZE -1; p != IntMSetA_rend(ima); p = IntMSetA_prev(p), i--) { | |
354 | +/* printf("%d, %d\n", i, IntMSetA_key(p));*/ | |
355 | + } | |
356 | + assert(i == -1); | |
357 | + assert(IntMSetA_prev(IntMSetA_begin(ima)) == IntMSetA_rend(ima)); | |
358 | + /* erase */ | |
359 | + for (i = 0; i < SIZE; i++) { | |
360 | + IntMSetAIterator itr = IntMSetA_next(pos[i]); | |
361 | + assert(itr == IntMSetA_erase(ima, pos[i])); | |
362 | + count--; | |
363 | + } | |
364 | + assert(IntMSetA_empty(ima)); | |
365 | + assert(IntMSetA_size(ima) == 0); | |
366 | + assert(count == 0); | |
367 | + /* erase_range */ | |
368 | + for (i = 0; i < SIZE; i++) { | |
369 | + pos[i] = IntMSetA_insert(ima, hoge_int[i]); | |
370 | + assert(pos[i] && pos[i] != IntMSetA_end(ima)); | |
371 | + } | |
372 | + assert(IntMSetA_size(ima) == SIZE); | |
373 | + assert(IntMSetA_next(IntMSetA_find(ima, SIZE/2/2 -1)) == IntMSetA_erase_range(ima, IntMSetA_find(ima, 0), IntMSetA_next(IntMSetA_find(ima, SIZE/2/2 -1)))); | |
374 | + assert(IntMSetA_size(ima) == SIZE - SIZE/2/2); | |
375 | + assert(IntMSetA_end(ima) == IntMSetA_erase_range(ima, IntMSetA_begin(ima), IntMSetA_end(ima))); | |
376 | + assert(IntMSetA_size(ima) == 0); | |
377 | + assert(IntMSetA_insert(ima, hoge_int[0])); | |
378 | + assert(IntMSetA_size(ima) == 1); | |
379 | + assert(IntMSetA_next(IntMSetA_begin(ima)) == IntMSetA_erase_range(ima, IntMSetA_begin(ima), IntMSetA_next(IntMSetA_begin(ima)))); | |
380 | + assert(IntMSetA_size(ima) == 0); | |
381 | + assert(IntMSetA_insert(ima, 100)); | |
382 | + assert(IntMSetA_insert(ima, 100)); | |
383 | + assert(IntMSetA_insert(ima, 100)); | |
384 | + assert(IntMSetA_insert(ima, 110)); | |
385 | + assert(IntMSetA_insert(ima, 110)); | |
386 | + assert(IntMSetA_size(ima) == 5); | |
387 | + assert(IntMSetA_upper_bound(ima, 110) == IntMSetA_erase_range(ima, IntMSetA_lower_bound(ima, 100), IntMSetA_upper_bound(ima, 110))); | |
388 | + assert(IntMSetA_size(ima) == 0); | |
389 | + /* erase_key */ | |
390 | + for (i = 0; i < SIZE; i++) { | |
391 | + pos[i] = IntMSetA_insert(ima, hoge_int[i]); | |
392 | + assert(pos[i] && pos[i] != IntMSetA_end(ima)); | |
393 | + } | |
394 | + assert(IntMSetA_size(ima) == SIZE); | |
395 | + for (i = 0; i < SIZE/2/2; i++) { | |
396 | + assert(IntMSetA_erase_key(ima, i) == 1); | |
397 | + } | |
398 | + assert(IntMSetA_size(ima) == SIZE - SIZE/2/2); | |
399 | + for (i = SIZE/2/2; i < SIZE/2; i++) { | |
400 | + assert(IntMSetA_erase_key(ima, i) == 3); | |
401 | + } | |
402 | + assert(IntMSetA_size(ima) == 0); | |
403 | + /* 大量にinsert */ | |
404 | + count = 0; | |
405 | + while (count < 1000000 && IntMSetA_insert(ima, 0)) { | |
406 | + count++; | |
407 | + } | |
408 | + assert(IntMSetA_size(ima) == count); | |
409 | + printf("count: %d\n", count); | |
410 | + | |
411 | + IntMSetA_delete(ima); | |
412 | +} | |
413 | + | |
414 | +void SetTest_test_2_1(void) | |
415 | +{ | |
416 | + int i; | |
417 | + int success[SIZE]; | |
418 | + size_t count = 0; | |
419 | + DoubleSetAIterator pos[SIZE]; | |
420 | + DoubleSetAIterator p; | |
421 | + printf("***** test_2_1 *****\n"); | |
422 | + da = DoubleSetA_new(); | |
423 | + /* 初期状態 */ | |
424 | + assert(DoubleSetA_empty(da)); | |
425 | + assert(DoubleSetA_size(da) == 0); | |
426 | + assert(DoubleSetA_begin(da) == DoubleSetA_end(da)); | |
427 | + assert(DoubleSetA_rbegin(da) == DoubleSetA_rend(da)); | |
428 | + /* insert */ | |
429 | + for (i = 0; i < SIZE; i++) { | |
430 | + pos[i] = DoubleSetA_insert(da, hoge_double[i], &success[i]); | |
431 | + if (i < SIZE/2) { | |
432 | + assert(success[i]); | |
433 | + count++; | |
434 | + } else { | |
435 | + assert(!success[i]); | |
436 | + } | |
437 | + assert(pos[i]); | |
438 | + } | |
439 | + assert(!DoubleSetA_empty(da)); | |
440 | + assert(DoubleSetA_size(da) == count); | |
441 | + assert(count == SIZE/2); | |
442 | + /* count, find, lower_bound, upper_bound */ | |
443 | + for (i = 0; i < SIZE/2; i++) { | |
444 | + assert(DoubleSetA_count(da, hoge_double[i]) == 1); | |
445 | + assert(pos[i] == DoubleSetA_find(da, hoge_double[i])); | |
446 | + assert(pos[i] == DoubleSetA_lower_bound(da, hoge_double[i])); | |
447 | + assert(pos[i] == DoubleSetA_upper_bound(da, hoge_double[i]-0.5)); | |
448 | + assert(DoubleSetA_lower_bound(da, hoge_double[i]+0.5) == DoubleSetA_upper_bound(da, hoge_double[i])); | |
449 | + } | |
450 | + assert(DoubleSetA_find(da, DoubleSetA_key(DoubleSetA_begin(da)) -1) == DoubleSetA_end(da)); | |
451 | + assert(DoubleSetA_lower_bound(da, DoubleSetA_key(DoubleSetA_rbegin(da)) +1) == DoubleSetA_end(da)); | |
452 | + assert(DoubleSetA_upper_bound(da, DoubleSetA_key(DoubleSetA_rbegin(da))) == DoubleSetA_end(da)); | |
453 | + /* begin, end, next, key */ | |
454 | + for (p = DoubleSetA_begin(da), i = 0; p != DoubleSetA_end(da); p = DoubleSetA_next(p), i++) { | |
455 | + assert(DoubleSetA_key(p) == i*0.5); | |
456 | + } | |
457 | + assert(i == SIZE/2); | |
458 | + assert(DoubleSetA_next(DoubleSetA_rbegin(da)) == DoubleSetA_end(da)); | |
459 | + /* rbegin, rend, prev, key */ | |
460 | + for (p = DoubleSetA_rbegin(da), i = SIZE/2 -1; p != DoubleSetA_rend(da); p = DoubleSetA_prev(p), i--) { | |
461 | + assert(DoubleSetA_key(p) == i*0.5); | |
462 | + } | |
463 | + assert(i == -1); | |
464 | + assert(DoubleSetA_prev(DoubleSetA_begin(da)) == DoubleSetA_rend(da)); | |
465 | + /* erase */ | |
466 | + for (i = 0; i < SIZE; i++) { | |
467 | + if (pos[i] && success[i]) { | |
468 | + DoubleSetAIterator itr = DoubleSetA_next(pos[i]); | |
469 | + assert(itr == DoubleSetA_erase(da, pos[i])); | |
470 | + count--; | |
471 | + } | |
472 | + } | |
473 | + assert(DoubleSetA_empty(da)); | |
474 | + assert(DoubleSetA_size(da) == 0); | |
475 | + assert(count == 0); | |
476 | + /* erase_range */ | |
477 | + for (i = 0; i < SIZE/2; i++) { | |
478 | + pos[i] = DoubleSetA_insert(da, hoge_double[i], NULL); | |
479 | + assert(pos[i]); | |
480 | + } | |
481 | + assert(DoubleSetA_size(da) == SIZE/2); | |
482 | + assert(DoubleSetA_find(da, SIZE/2 -2) == DoubleSetA_erase_range(da, DoubleSetA_find(da, 2), DoubleSetA_find(da, SIZE/2 -2))); | |
483 | + assert(DoubleSetA_size(da) == 4); | |
484 | + assert(DoubleSetA_end(da) == DoubleSetA_erase_range(da, DoubleSetA_begin(da), DoubleSetA_end(da))); | |
485 | + assert(DoubleSetA_size(da) == 0); | |
486 | + assert(DoubleSetA_insert(da, hoge_double[0], NULL)); | |
487 | + assert(DoubleSetA_size(da) == 1); | |
488 | + assert(DoubleSetA_next(DoubleSetA_begin(da)) == DoubleSetA_erase_range(da, DoubleSetA_begin(da), DoubleSetA_next(DoubleSetA_begin(da)))); | |
489 | + assert(DoubleSetA_size(da) == 0); | |
490 | + assert(DoubleSetA_insert(da, 100.1, NULL)); | |
491 | + assert(DoubleSetA_insert(da, 110.1, NULL)); | |
492 | + assert(DoubleSetA_size(da) == 2); | |
493 | + assert(DoubleSetA_upper_bound(da, 110.1) == DoubleSetA_erase_range(da, DoubleSetA_lower_bound(da, 100.1), DoubleSetA_upper_bound(da, 110.1))); | |
494 | + assert(DoubleSetA_size(da) == 0); | |
495 | + /* erase_key */ | |
496 | + for (i = 0; i < SIZE/2; i++) { | |
497 | + pos[i] = DoubleSetA_insert(da, hoge_double[i], NULL); | |
498 | + assert(pos[i]); | |
499 | + } | |
500 | + assert(DoubleSetA_size(da) == SIZE/2); | |
501 | + for (i = 0; i < SIZE/2; i++) { | |
502 | + assert(DoubleSetA_erase_key(da, hoge_double[i]) == 1); | |
503 | + } | |
504 | + assert(DoubleSetA_size(da) == 0); | |
505 | + /* 大量にinsert */ | |
506 | + count = 0; | |
507 | + while (count < 1000000 && DoubleSetA_insert(da, count, NULL)) { | |
508 | + count++; | |
509 | + } | |
510 | + assert(DoubleSetA_size(da) == count); | |
511 | + printf("count: %d\n", count); | |
512 | + printf("size: %d\n", DoubleSetA_size(da)); | |
513 | + /* clear */ | |
514 | + DoubleSetA_clear(da); | |
515 | + printf("size: %d\n", DoubleSetA_size(da)); | |
516 | + assert(DoubleSetA_size(da) == 0); | |
517 | + assert(DoubleSetA_insert(da, 100, NULL)); | |
518 | + assert(DoubleSetA_size(da) == 1); | |
519 | + DoubleSetA_clear(da); | |
520 | + assert(DoubleSetA_size(da) == 0); | |
521 | + DoubleSetA_clear(da); | |
522 | + assert(DoubleSetA_size(da) == 0); | |
523 | + | |
524 | + DoubleSetA_delete(da); | |
525 | +} | |
526 | + | |
527 | +void SetTest_test_3_1(void) | |
528 | +{ | |
529 | + int i; | |
530 | + int success[SIZE]; | |
531 | + size_t count = 0; | |
532 | + int *intp = NULL; | |
533 | + PtrSetAIterator pos[SIZE]; | |
534 | + PtrSetAIterator p; | |
535 | + printf("***** test_3_1 *****\n"); | |
536 | + pa = PtrSetA_new(); | |
537 | + /* 初期状態 */ | |
538 | + assert(PtrSetA_empty(pa)); | |
539 | + assert(PtrSetA_size(pa) == 0); | |
540 | + assert(PtrSetA_begin(pa) == PtrSetA_end(pa)); | |
541 | + assert(PtrSetA_rbegin(pa) == PtrSetA_rend(pa)); | |
542 | + /* insert */ | |
543 | + for (i = 0; i < SIZE; i++) { | |
544 | + pos[i] = PtrSetA_insert(pa, hoge_ptr[i], &success[i]); | |
545 | + if (i < SIZE/2) { | |
546 | + assert(success[i]); | |
547 | + count++; | |
548 | + } else { | |
549 | + assert(!success[i]); | |
550 | + } | |
551 | + assert(pos[i]); | |
552 | + } | |
553 | + assert(!PtrSetA_empty(pa)); | |
554 | + assert(PtrSetA_size(pa) == count); | |
555 | + assert(count == SIZE/2); | |
556 | + /* count, find, lower_bound, upper_bound */ | |
557 | + for (i = 0; i < SIZE/2; i++) { | |
558 | + assert(PtrSetA_count(pa, hoge_ptr[i]) == 1); | |
559 | + assert(pos[i] == PtrSetA_find(pa, hoge_ptr[i])); | |
560 | + assert(pos[i] == PtrSetA_lower_bound(pa, hoge_ptr[i])); | |
561 | + assert(pos[i] == PtrSetA_upper_bound(pa, hoge_ptr[i]-1)); | |
562 | + assert(PtrSetA_lower_bound(pa, hoge_ptr[i]+1) == PtrSetA_upper_bound(pa, hoge_ptr[i])); | |
563 | + } | |
564 | + assert(PtrSetA_find(pa, PtrSetA_key(PtrSetA_begin(pa)) -1) == PtrSetA_end(pa)); | |
565 | + assert(PtrSetA_lower_bound(pa, PtrSetA_key(PtrSetA_rbegin(pa)) +1) == PtrSetA_end(pa)); | |
566 | + assert(PtrSetA_upper_bound(pa, PtrSetA_key(PtrSetA_rbegin(pa))) == PtrSetA_end(pa)); | |
567 | + /* begin, end, next, key */ | |
568 | + for (p = PtrSetA_begin(pa), i = 0; p != PtrSetA_end(pa); p = PtrSetA_next(p), i++) { | |
569 | + assert(PtrSetA_key(p) == &hoge_int[i]); | |
570 | + } | |
571 | + assert(i == SIZE/2); | |
572 | + assert(PtrSetA_next(PtrSetA_rbegin(pa)) == PtrSetA_end(pa)); | |
573 | + /* rbegin, rend, prev, key */ | |
574 | + for (p = PtrSetA_rbegin(pa), i = SIZE/2 -1; p != PtrSetA_rend(pa); p = PtrSetA_prev(p), i--) { | |
575 | + assert(PtrSetA_key(p) == &hoge_int[i]); | |
576 | + } | |
577 | + assert(i == -1); | |
578 | + assert(PtrSetA_prev(PtrSetA_begin(pa)) == PtrSetA_rend(pa)); | |
579 | + /* erase */ | |
580 | + for (i = 0; i < SIZE; i++) { | |
581 | + if (pos[i] && success[i]) { | |
582 | + PtrSetAIterator itr = PtrSetA_next(pos[i]); | |
583 | + assert(itr == PtrSetA_erase(pa, pos[i])); | |
584 | + count--; | |
585 | + } | |
586 | + } | |
587 | + assert(PtrSetA_empty(pa)); | |
588 | + assert(PtrSetA_size(pa) == 0); | |
589 | + assert(count == 0); | |
590 | + /* erase_range */ | |
591 | + for (i = 0; i < SIZE/2; i++) { | |
592 | + pos[i] = PtrSetA_insert(pa, hoge_ptr[i], NULL); | |
593 | + assert(pos[i]); | |
594 | + } | |
595 | + assert(PtrSetA_size(pa) == SIZE/2); | |
596 | + assert(PtrSetA_find(pa, &hoge_int[SIZE/2 -2]) == PtrSetA_erase_range(pa, PtrSetA_find(pa, &hoge_int[2]), PtrSetA_find(pa, &hoge_int[SIZE/2 -2]))); | |
597 | + assert(PtrSetA_size(pa) == 4); | |
598 | + assert(PtrSetA_end(pa) == PtrSetA_erase_range(pa, PtrSetA_begin(pa), PtrSetA_end(pa))); | |
599 | + assert(PtrSetA_size(pa) == 0); | |
600 | + assert(PtrSetA_insert(pa, hoge_ptr[0], NULL)); | |
601 | + assert(PtrSetA_size(pa) == 1); | |
602 | + assert(PtrSetA_next(PtrSetA_begin(pa)) == PtrSetA_erase_range(pa, PtrSetA_begin(pa), PtrSetA_next(PtrSetA_begin(pa)))); | |
603 | + assert(PtrSetA_size(pa) == 0); | |
604 | + assert(PtrSetA_insert(pa, (int*)100, NULL)); | |
605 | + assert(PtrSetA_insert(pa, (int*)100 + 1, NULL)); | |
606 | + assert(PtrSetA_size(pa) == 2); | |
607 | + assert(PtrSetA_upper_bound(pa, (int*)100 + 1) == PtrSetA_erase_range(pa, PtrSetA_lower_bound(pa, (int*)100), PtrSetA_upper_bound(pa, (int*)100 + 1))); | |
608 | + assert(PtrSetA_size(pa) == 0); | |
609 | + /* erase_key */ | |
610 | + for (i = 0; i < SIZE/2; i++) { | |
611 | + pos[i] = PtrSetA_insert(pa, hoge_ptr[i], NULL); | |
612 | + assert(pos[i]); | |
613 | + } | |
614 | + assert(PtrSetA_size(pa) == SIZE/2); | |
615 | + for (i = 0; i < SIZE/2; i++) { | |
616 | + assert(PtrSetA_erase_key(pa, hoge_ptr[i]) == 1); | |
617 | + } | |
618 | + assert(PtrSetA_size(pa) == 0); | |
619 | + /* 大量にinsert */ | |
620 | + count = 0; | |
621 | + while (count < 1000000 && PtrSetA_insert(pa, intp, NULL)) { | |
622 | + count++; | |
623 | + intp++; | |
624 | + } | |
625 | + assert(PtrSetA_size(pa) == count); | |
626 | + printf("count: %d\n", count); | |
627 | + printf("size: %d\n", PtrSetA_size(pa)); | |
628 | + /* clear */ | |
629 | + PtrSetA_clear(pa); | |
630 | + printf("size: %d\n", PtrSetA_size(pa)); | |
631 | + assert(PtrSetA_size(pa) == 0); | |
632 | + assert(PtrSetA_insert(pa, intp, NULL)); | |
633 | + assert(PtrSetA_size(pa) == 1); | |
634 | + PtrSetA_clear(pa); | |
635 | + assert(PtrSetA_size(pa) == 0); | |
636 | + PtrSetA_clear(pa); | |
637 | + assert(PtrSetA_size(pa) == 0); | |
638 | + | |
639 | + PtrSetA_delete(pa); | |
640 | +} | |
641 | + | |
642 | +void SetTest_test_4_1(void) | |
643 | +{ | |
644 | + int i; | |
645 | + int success[SIZE]; | |
646 | + size_t count = 0; | |
647 | + StrSetAIterator pos[SIZE]; | |
648 | + StrSetAIterator p; | |
649 | + printf("***** test_4_1 *****\n"); | |
650 | + sa = StrSetA_new(); | |
651 | + /* 初期状態 */ | |
652 | + assert(StrSetA_empty(sa)); | |
653 | + assert(StrSetA_size(sa) == 0); | |
654 | + assert(StrSetA_begin(sa) == StrSetA_end(sa)); | |
655 | + assert(StrSetA_rbegin(sa) == StrSetA_rend(sa)); | |
656 | + /* insert */ | |
657 | + for (i = 0; i < SIZE; i++) { | |
658 | + pos[i] = StrSetA_insert(sa, hoge_str[i], &success[i]); | |
659 | + if (i < SIZE/2) { | |
660 | + assert(success[i]); | |
661 | + count++; | |
662 | + } else { | |
663 | + assert(!success[i]); | |
664 | + } | |
665 | + assert(pos[i]); | |
666 | + } | |
667 | +/* StrSetA_print(sa);*/ | |
668 | + assert(!StrSetA_empty(sa)); | |
669 | + assert(StrSetA_size(sa) == count); | |
670 | + assert(count == SIZE/2); | |
671 | + /* count, find, lower_bound, upper_bound */ | |
672 | + for (i = 0; i < SIZE/2; i++) { | |
673 | + assert(StrSetA_count(sa, hoge_str[i]) == 1); | |
674 | + assert(pos[i] == StrSetA_find(sa, hoge_str[i])); | |
675 | + assert(pos[i] == StrSetA_lower_bound(sa, hoge_str[i])); | |
676 | + if (i != SIZE/2-1) { | |
677 | + assert(pos[i+1] == StrSetA_upper_bound(sa, hoge_str[i])); | |
678 | + assert(StrSetA_lower_bound(sa, hoge_str[i+1]) == StrSetA_upper_bound(sa, hoge_str[i])); | |
679 | + } | |
680 | + } | |
681 | + assert(StrSetA_find(sa, "hoge") == StrSetA_end(sa)); | |
682 | + assert(StrSetA_lower_bound(sa, "hoge") == StrSetA_end(sa)); | |
683 | + assert(StrSetA_upper_bound(sa, StrSetA_key(StrSetA_rbegin(sa))) == StrSetA_end(sa)); | |
684 | + /* begin, end, next, key */ | |
685 | + for (p = StrSetA_begin(sa), i = 0; p != StrSetA_end(sa); p = StrSetA_next(p), i++) { | |
686 | + assert(StrSetA_key(p) == hoge_str[i]); | |
687 | + } | |
688 | + assert(i == SIZE/2); | |
689 | + assert(StrSetA_next(StrSetA_rbegin(sa)) == StrSetA_end(sa)); | |
690 | + /* rbegin, rend, prev, key */ | |
691 | + for (p = StrSetA_rbegin(sa), i = SIZE/2 -1; p != StrSetA_rend(sa); p = StrSetA_prev(p), i--) { | |
692 | + assert(StrSetA_key(p) == hoge_str[i]); | |
693 | + } | |
694 | + assert(i == -1); | |
695 | + assert(StrSetA_prev(StrSetA_begin(sa)) == StrSetA_rend(sa)); | |
696 | + /* erase */ | |
697 | + for (i = 0; i < SIZE; i++) { | |
698 | + if (pos[i] && success[i]) { | |
699 | + StrSetAIterator itr = StrSetA_next(pos[i]); | |
700 | + assert(itr == StrSetA_erase(sa, pos[i])); | |
701 | + count--; | |
702 | + } | |
703 | + } | |
704 | + assert(StrSetA_empty(sa)); | |
705 | + assert(StrSetA_size(sa) == 0); | |
706 | + assert(count == 0); | |
707 | + /* erase_range */ | |
708 | + for (i = 0; i < SIZE/2; i++) { | |
709 | + pos[i] = StrSetA_insert(sa, hoge_str[i], NULL); | |
710 | + assert(pos[i]); | |
711 | + } | |
712 | + assert(StrSetA_size(sa) == SIZE/2); | |
713 | + assert(StrSetA_find(sa, hoge_str[SIZE/2 -2]) == StrSetA_erase_range(sa, StrSetA_find(sa, hoge_str[2]), StrSetA_find(sa, hoge_str[SIZE/2 -2]))); | |
714 | + assert(StrSetA_size(sa) == 4); | |
715 | + assert(StrSetA_end(sa) == StrSetA_erase_range(sa, StrSetA_begin(sa), StrSetA_end(sa))); | |
716 | + assert(StrSetA_size(sa) == 0); | |
717 | + assert(StrSetA_insert(sa, hoge_str[0], NULL)); | |
718 | + assert(StrSetA_size(sa) == 1); | |
719 | + assert(StrSetA_next(StrSetA_begin(sa)) == StrSetA_erase_range(sa, StrSetA_begin(sa), StrSetA_next(StrSetA_begin(sa)))); | |
720 | + assert(StrSetA_size(sa) == 0); | |
721 | + assert(StrSetA_insert(sa, "100", NULL)); | |
722 | + assert(StrSetA_insert(sa, "110", NULL)); | |
723 | + assert(StrSetA_size(sa) == 2); | |
724 | + assert(StrSetA_upper_bound(sa, "110") == StrSetA_erase_range(sa, StrSetA_lower_bound(sa, "100"), StrSetA_upper_bound(sa, "110"))); | |
725 | + assert(StrSetA_size(sa) == 0); | |
726 | + /* erase_key */ | |
727 | + for (i = 0; i < SIZE/2; i++) { | |
728 | + pos[i] = StrSetA_insert(sa, hoge_str[i], NULL); | |
729 | + assert(pos[i]); | |
730 | + } | |
731 | + assert(StrSetA_size(sa) == SIZE/2); | |
732 | + for (i = 0; i < SIZE/2; i++) { | |
733 | + assert(StrSetA_erase_key(sa, hoge_str[i]) == 1); | |
734 | + } | |
735 | + assert(StrSetA_size(sa) == 0); | |
736 | + /* clear */ | |
737 | + assert(StrSetA_insert(sa, "103", NULL)); | |
738 | + assert(StrSetA_insert(sa, "101", NULL)); | |
739 | + assert(StrSetA_insert(sa, "100", NULL)); | |
740 | + assert(StrSetA_insert(sa, "104", NULL)); | |
741 | + assert(StrSetA_insert(sa, "106", NULL)); | |
742 | + assert(StrSetA_insert(sa, "105", NULL)); | |
743 | + assert(StrSetA_insert(sa, "102", NULL)); | |
744 | + printf("size: %d\n", StrSetA_size(sa)); | |
745 | + StrSetA_clear(sa); | |
746 | + printf("size: %d\n", StrSetA_size(sa)); | |
747 | + assert(StrSetA_size(sa) == 0); | |
748 | + assert(StrSetA_insert(sa, "100", NULL)); | |
749 | + assert(StrSetA_size(sa) == 1); | |
750 | + StrSetA_clear(sa); | |
751 | + assert(StrSetA_size(sa) == 0); | |
752 | + StrSetA_clear(sa); | |
753 | + assert(StrSetA_size(sa) == 0); | |
754 | + | |
755 | + StrSetA_delete(sa); | |
756 | +} | |
757 | + | |
758 | + | |
759 | + | |
760 | + | |
761 | + | |
762 | + | |
763 | + | |
764 | + | |
765 | + | |
766 | + | |
767 | + | |
768 | + | |
769 | + | |
770 | +void SetTest_run(void) | |
771 | +{ | |
772 | + printf("\n===== set test =====\n"); | |
773 | + set_init_hoge(); | |
774 | + | |
775 | + SetTest_test_1_1(); | |
776 | + SetTest_test_1_2(); | |
777 | + SetTest_test_1_3(); | |
778 | + SetTest_test_2_1(); | |
779 | + SetTest_test_3_1(); | |
780 | + SetTest_test_4_1(); | |
781 | + | |
782 | + | |
783 | +} | |
784 | + |
@@ -0,0 +1,35 @@ | ||
1 | +CC=gcc | |
2 | +# MEMORY=-DHEAP_DEBUG -DMY_MALLOC | |
3 | +CFLAGS=-Wall -g $(MEMORY) | |
4 | + | |
5 | +all: test | |
6 | +clean: | |
7 | + rm -f *.exe *.o | |
8 | + | |
9 | +heap.o: ../heap.c ../heap.h | |
10 | + $(CC) $(CFLAGS) -c ../heap.c | |
11 | + | |
12 | +vector_test.o: ../cstl/vector.h vector_test.c heap.o | |
13 | + $(CC) $(CFLAGS) -c vector_test.c | |
14 | + | |
15 | +deque_test.o: ../cstl/deque.h deque_test.c heap.o | |
16 | + $(CC) $(CFLAGS) -c deque_test.c | |
17 | + | |
18 | +list_test.o: ../cstl/list.h list_test.c heap.o | |
19 | + $(CC) $(CFLAGS) -c list_test.c | |
20 | + | |
21 | +set_test.o: ../cstl/set.h ../cstl/rbtree.h set_test.c heap.o rbtree_debug.h | |
22 | + $(CC) $(CFLAGS) -c set_test.c | |
23 | + | |
24 | +map_test.o: ../cstl/map.h ../cstl/rbtree.h map_test.c heap.o rbtree_debug.h | |
25 | + $(CC) $(CFLAGS) -c map_test.c | |
26 | + | |
27 | +string_test.o: ../cstl/string.h string_test.cpp heap.o | |
28 | + g++ $(CFLAGS) -c string_test.cpp | |
29 | + | |
30 | +test: test.h main.c vector_test.o deque_test.o list_test.o set_test.o map_test.o string_test.o | |
31 | + $(CC) $(CFLAGS) -o $@.exe main.c heap.o vector_test.o deque_test.o list_test.o set_test.o map_test.o | |
32 | + ./$@.exe | |
33 | + g++ -o string_test.exe heap.o string_test.o | |
34 | + ./string_test.exe | |
35 | + |
@@ -0,0 +1,328 @@ | ||
1 | +#include "test.h" | |
2 | + | |
3 | +#include <time.h> | |
4 | + | |
5 | +/* int */ | |
6 | +MAP_IMPLEMENT(IntIntMapA, int, int, SIMPLE_CMP, ASC) | |
7 | +MAP_DEBUG_IMPLEMENT(IntIntMapA, int, int, SIMPLE_CMP, ASC, %d, %d, VISUAL) | |
8 | +static IntIntMapA *ia; | |
9 | + | |
10 | +MULTIMAP_IMPLEMENT(IntIntMMapA, int, int, SIMPLE_CMP, ASC) | |
11 | +MAP_DEBUG_IMPLEMENT(IntIntMMapA, int, int, SIMPLE_CMP, ASC, %d, %d, VISUAL) | |
12 | +static IntIntMMapA *ima; | |
13 | + | |
14 | + | |
15 | + | |
16 | +#define SIZE 32 | |
17 | +static int hoge_int[SIZE]; | |
18 | +static double hoge_double[SIZE]; | |
19 | +static int *hoge_ptr[SIZE]; | |
20 | +static char *hoge_str[SIZE]; | |
21 | +static char str[SIZE][16]; | |
22 | + | |
23 | +void map_init_hoge(void) | |
24 | +{ | |
25 | + int i; | |
26 | + int tmp; | |
27 | + IntDeque *q = IntDeque_new(SIZE/2); | |
28 | + srand(time(0)); | |
29 | +/* printf("hoge data\n");*/ | |
30 | + for (i = 0; i < SIZE/2; i++) { | |
31 | + IntDeque_push_back(q, i); | |
32 | + } | |
33 | + for (i = 0; i < SIZE; i++) { | |
34 | + if (!IntDeque_empty(q)) { | |
35 | + int rnd = rand() % IntDeque_size(q); | |
36 | + tmp = *IntDeque_at(q, rnd); | |
37 | + IntDeque_erase(q, rnd); | |
38 | + } else { | |
39 | + tmp = i/2; | |
40 | + } | |
41 | + hoge_int[i] = tmp; | |
42 | + hoge_double[i] = hoge_int[i] * 0.5; | |
43 | + hoge_ptr[i] = &hoge_int[tmp]; | |
44 | + sprintf(str[i], "%05d", i < SIZE/2 ? i : tmp); | |
45 | + hoge_str[i] = str[i]; | |
46 | +/* printf("%4d: int[%3d], double[%5g], ptr[%p], str[%s]\n",*/ | |
47 | +/* i, hoge_int[i], hoge_double[i], hoge_ptr[i], hoge_str[i]);*/ | |
48 | + } | |
49 | + IntDeque_delete(q); | |
50 | +} | |
51 | + | |
52 | +void MapTest_test_1_1(void) | |
53 | +{ | |
54 | + int i; | |
55 | + int success[SIZE]; | |
56 | + size_t count = 0; | |
57 | + IntIntMapAIterator pos[SIZE]; | |
58 | + IntIntMapAIterator p; | |
59 | + printf("***** test_1_1 *****\n"); | |
60 | + ia = IntIntMapA_new(); | |
61 | + /* 初期状態 */ | |
62 | + assert(IntIntMapA_empty(ia)); | |
63 | + assert(IntIntMapA_size(ia) == 0); | |
64 | + assert(IntIntMapA_begin(ia) == IntIntMapA_end(ia)); | |
65 | + assert(IntIntMapA_rbegin(ia) == IntIntMapA_rend(ia)); | |
66 | + /* insert */ | |
67 | + for (i = 0; i < SIZE; i++) { | |
68 | + pos[i] = IntIntMapA_insert(ia, hoge_int[i], hoge_int[i], &success[i]); | |
69 | + if (i < SIZE/2) { | |
70 | + assert(success[i]); | |
71 | + count++; | |
72 | + } else { | |
73 | + assert(!success[i]); | |
74 | + } | |
75 | + assert(pos[i]); | |
76 | + } | |
77 | +/* IntIntMapA_print(ia);*/ | |
78 | + assert(!IntIntMapA_empty(ia)); | |
79 | + assert(IntIntMapA_size(ia) == count); | |
80 | + assert(count == SIZE/2); | |
81 | + /* count, find, lower_bound, upper_bound */ | |
82 | + for (i = 0; i < SIZE/2; i++) { | |
83 | + assert(IntIntMapA_count(ia, hoge_int[i]) == 1); | |
84 | + assert(pos[i] == IntIntMapA_find(ia, hoge_int[i])); | |
85 | + assert(pos[i] == IntIntMapA_lower_bound(ia, hoge_int[i])); | |
86 | + assert(pos[i] == IntIntMapA_upper_bound(ia, hoge_int[i]-1)); | |
87 | + assert(IntIntMapA_lower_bound(ia, hoge_int[i]+1) == IntIntMapA_upper_bound(ia, hoge_int[i])); | |
88 | + } | |
89 | + assert(IntIntMapA_find(ia, IntIntMapA_key(IntIntMapA_begin(ia)) -1) == IntIntMapA_end(ia)); | |
90 | + assert(IntIntMapA_lower_bound(ia, IntIntMapA_key(IntIntMapA_rbegin(ia)) +1) == IntIntMapA_end(ia)); | |
91 | + assert(IntIntMapA_upper_bound(ia, IntIntMapA_key(IntIntMapA_rbegin(ia))) == IntIntMapA_end(ia)); | |
92 | + /* begin, end, next, key, value, lookup */ | |
93 | + for (p = IntIntMapA_begin(ia), i = 0; p != IntIntMapA_end(ia); p = IntIntMapA_next(p), i++) { | |
94 | + assert(IntIntMapA_key(p) == i); | |
95 | + assert(*IntIntMapA_value(p) == i); | |
96 | + assert(*IntIntMapA_lookup(ia, IntIntMapA_key(p)) == i); | |
97 | + *IntIntMapA_value(p) = ~i; | |
98 | + assert(*IntIntMapA_lookup(ia, IntIntMapA_key(p)) == ~i); | |
99 | + *IntIntMapA_lookup(ia, IntIntMapA_key(p)) = i; | |
100 | + } | |
101 | + assert(i == SIZE/2); | |
102 | + assert(IntIntMapA_next(IntIntMapA_rbegin(ia)) == IntIntMapA_end(ia)); | |
103 | + /* rbegin, rend, prev, key, value, lookup */ | |
104 | + for (p = IntIntMapA_rbegin(ia), i = SIZE/2 -1; p != IntIntMapA_rend(ia); p = IntIntMapA_prev(p), i--) { | |
105 | + assert(IntIntMapA_key(p) == i); | |
106 | + assert(*IntIntMapA_value(p) == i); | |
107 | + assert(*IntIntMapA_lookup(ia, IntIntMapA_key(p)) == i); | |
108 | + *IntIntMapA_value(p) = ~i; | |
109 | + assert(*IntIntMapA_lookup(ia, IntIntMapA_key(p)) == ~i); | |
110 | + *IntIntMapA_lookup(ia, IntIntMapA_key(p)) = i; | |
111 | + } | |
112 | + assert(i == -1); | |
113 | + assert(IntIntMapA_prev(IntIntMapA_begin(ia)) == IntIntMapA_rend(ia)); | |
114 | + /* erase */ | |
115 | + for (i = 0; i < SIZE; i++) { | |
116 | + if (pos[i] && success[i]) { | |
117 | + IntIntMapAIterator itr = IntIntMapA_next(pos[i]); | |
118 | + assert(itr == IntIntMapA_erase(ia, pos[i])); | |
119 | + count--; | |
120 | + } | |
121 | + } | |
122 | + assert(IntIntMapA_empty(ia)); | |
123 | + assert(IntIntMapA_size(ia) == 0); | |
124 | + assert(count == 0); | |
125 | + /* erase_range */ | |
126 | + for (i = 0; i < SIZE/2; i++) { | |
127 | + pos[i] = IntIntMapA_insert(ia, hoge_int[i], hoge_int[i], NULL); | |
128 | + assert(pos[i] && pos[i] != IntIntMapA_end(ia)); | |
129 | + } | |
130 | + assert(IntIntMapA_size(ia) == SIZE/2); | |
131 | + assert(IntIntMapA_find(ia, SIZE/2 -2) == IntIntMapA_erase_range(ia, IntIntMapA_find(ia, 2), IntIntMapA_find(ia, SIZE/2 -2))); | |
132 | + assert(IntIntMapA_size(ia) == 4); | |
133 | + assert(IntIntMapA_end(ia) == IntIntMapA_erase_range(ia, IntIntMapA_begin(ia), IntIntMapA_end(ia))); | |
134 | + assert(IntIntMapA_size(ia) == 0); | |
135 | + assert(IntIntMapA_insert(ia, hoge_int[0], hoge_int[0], NULL)); | |
136 | + assert(IntIntMapA_size(ia) == 1); | |
137 | + assert(IntIntMapA_next(IntIntMapA_begin(ia)) == IntIntMapA_erase_range(ia, IntIntMapA_begin(ia), IntIntMapA_next(IntIntMapA_begin(ia)))); | |
138 | + assert(IntIntMapA_size(ia) == 0); | |
139 | + assert(IntIntMapA_insert(ia, 100, 101, NULL)); | |
140 | + assert(IntIntMapA_insert(ia, 110, 111, NULL)); | |
141 | + assert(IntIntMapA_size(ia) == 2); | |
142 | + assert(IntIntMapA_upper_bound(ia, 110) == IntIntMapA_erase_range(ia, IntIntMapA_lower_bound(ia, 100), IntIntMapA_upper_bound(ia, 110))); | |
143 | + assert(IntIntMapA_size(ia) == 0); | |
144 | + /* erase_key */ | |
145 | + for (i = 0; i < SIZE/2; i++) { | |
146 | + pos[i] = IntIntMapA_insert(ia, hoge_int[i], hoge_int[i], NULL); | |
147 | + assert(pos[i] && pos[i] != IntIntMapA_end(ia)); | |
148 | + } | |
149 | + assert(IntIntMapA_size(ia) == SIZE/2); | |
150 | + for (i = 0; i < SIZE/2; i++) { | |
151 | + assert(IntIntMapA_erase_key(ia, hoge_int[i]) == 1); | |
152 | + } | |
153 | + assert(IntIntMapA_size(ia) == 0); | |
154 | + /* 大量にinsert */ | |
155 | + count = 0; | |
156 | + while (count < 1000000 && IntIntMapA_insert(ia, count, 9999, NULL)) { | |
157 | + count++; | |
158 | + } | |
159 | + assert(IntIntMapA_size(ia) == count); | |
160 | + printf("count: %d\n", count); | |
161 | + printf("size: %d\n", IntIntMapA_size(ia)); | |
162 | + /* clear */ | |
163 | + IntIntMapA_clear(ia); | |
164 | + printf("size: %d\n", IntIntMapA_size(ia)); | |
165 | + assert(IntIntMapA_size(ia) == 0); | |
166 | + assert(IntIntMapA_insert(ia, 100, 123, NULL)); | |
167 | + assert(IntIntMapA_size(ia) == 1); | |
168 | + IntIntMapA_clear(ia); | |
169 | + assert(IntIntMapA_size(ia) == 0); | |
170 | + IntIntMapA_clear(ia); | |
171 | + assert(IntIntMapA_size(ia) == 0); | |
172 | + | |
173 | + /* lookup */ | |
174 | + /* 挿入 */ | |
175 | + *IntIntMapA_lookup(ia, 1) = 482; | |
176 | + *IntIntMapA_lookup(ia, 2) = 4; | |
177 | + *IntIntMapA_lookup(ia, 3) = 554; | |
178 | + *IntIntMapA_lookup(ia, 4) = 44; | |
179 | + *IntIntMapA_lookup(ia, 5) = 89; | |
180 | +/* IntIntMapA_print(ia);*/ | |
181 | + /* 書換え */ | |
182 | + *IntIntMapA_lookup(ia, 1) = 82; | |
183 | +/* IntIntMapA_print(ia);*/ | |
184 | + | |
185 | + IntIntMapA_delete(ia); | |
186 | +} | |
187 | + | |
188 | +void MapTest_test_1_2(void) | |
189 | +{ | |
190 | + int i; | |
191 | + size_t count = 0; | |
192 | + IntIntMMapAIterator pos[SIZE]; | |
193 | + IntIntMMapAIterator p; | |
194 | + int flag[SIZE/2] = {0}; | |
195 | + printf("***** test_1_2 *****\n"); | |
196 | + ima = IntIntMMapA_new(); | |
197 | + /* 初期状態 */ | |
198 | + assert(IntIntMMapA_empty(ima)); | |
199 | + assert(IntIntMMapA_size(ima) == 0); | |
200 | + assert(IntIntMMapA_begin(ima) == IntIntMMapA_end(ima)); | |
201 | + assert(IntIntMMapA_rbegin(ima) == IntIntMMapA_rend(ima)); | |
202 | + /* insert */ | |
203 | + for (i = 0; i < SIZE; i++) { | |
204 | + pos[i] = IntIntMMapA_insert(ima, hoge_int[i], hoge_int[i]); | |
205 | + assert(pos[i] && pos[i] != IntIntMMapA_end(ima)); | |
206 | + count++; | |
207 | + } | |
208 | +/* IntIntMMapA_print(ima);*/ | |
209 | + assert(!IntIntMMapA_empty(ima)); | |
210 | + assert(IntIntMMapA_size(ima) == count); | |
211 | + assert(count == SIZE); | |
212 | + /* count */ | |
213 | + for (i = 0; i < SIZE; i++) { | |
214 | + if (i < SIZE/2/2) { | |
215 | + assert(IntIntMMapA_count(ima, i) == 1); | |
216 | + } else if (i < SIZE/2) { | |
217 | + assert(IntIntMMapA_count(ima, i) == 3); | |
218 | + } else { | |
219 | + assert(IntIntMMapA_count(ima, i) == 0); | |
220 | + } | |
221 | + } | |
222 | + /* find, lower_bound, upper_bound */ | |
223 | + for (i = 0; i < SIZE; i++) { | |
224 | + if (IntIntMMapA_count(ima, hoge_int[i]) == 1) { | |
225 | + assert(pos[i] == IntIntMMapA_find(ima, hoge_int[i])); | |
226 | + assert(pos[i] == IntIntMMapA_lower_bound(ima, hoge_int[i])); | |
227 | + assert(pos[i] == IntIntMMapA_upper_bound(ima, hoge_int[i]-1)); | |
228 | + } else if (IntIntMMapA_count(ima, hoge_int[i]) == 3) { | |
229 | + if (!flag[hoge_int[i]]) { | |
230 | + flag[hoge_int[i]] = 1; | |
231 | + assert(pos[i] == IntIntMMapA_lower_bound(ima, hoge_int[i])); | |
232 | + assert(pos[i] == IntIntMMapA_upper_bound(ima, hoge_int[i]-1)); | |
233 | + } | |
234 | + } else { | |
235 | + assert(0); | |
236 | + } | |
237 | + assert(IntIntMMapA_lower_bound(ima, hoge_int[i]+1) == IntIntMMapA_upper_bound(ima, hoge_int[i])); | |
238 | + } | |
239 | + assert(IntIntMMapA_find(ima, IntIntMMapA_key(IntIntMMapA_begin(ima)) -1) == IntIntMMapA_end(ima)); | |
240 | + assert(IntIntMMapA_lower_bound(ima, IntIntMMapA_key(IntIntMMapA_rbegin(ima)) +1) == IntIntMMapA_end(ima)); | |
241 | + assert(IntIntMMapA_upper_bound(ima, IntIntMMapA_key(IntIntMMapA_rbegin(ima))) == IntIntMMapA_end(ima)); | |
242 | + /* begin, end, next, key, value */ | |
243 | + for (p = IntIntMMapA_begin(ima), i = 0; p != IntIntMMapA_end(ima); p = IntIntMMapA_next(p), i++) { | |
244 | +/* printf("%d, %d, %d\n", i, IntIntMMapA_key(p), *IntIntMMapA_value(p));*/ | |
245 | + } | |
246 | + assert(i == SIZE); | |
247 | + assert(IntIntMMapA_next(IntIntMMapA_rbegin(ima)) == IntIntMMapA_end(ima)); | |
248 | + /* rbegin, rend, prev, key, value */ | |
249 | + for (p = IntIntMMapA_rbegin(ima), i = SIZE -1; p != IntIntMMapA_rend(ima); p = IntIntMMapA_prev(p), i--) { | |
250 | +/* printf("%d, %d, %d\n", i, IntIntMMapA_key(p), *IntIntMMapA_value(ima, p));*/ | |
251 | + } | |
252 | + assert(i == -1); | |
253 | + assert(IntIntMMapA_prev(IntIntMMapA_begin(ima)) == IntIntMMapA_rend(ima)); | |
254 | + /* erase */ | |
255 | + for (i = 0; i < SIZE; i++) { | |
256 | + IntIntMMapAIterator itr = IntIntMMapA_next(pos[i]); | |
257 | + assert(itr == IntIntMMapA_erase(ima, pos[i])); | |
258 | + count--; | |
259 | + } | |
260 | + assert(IntIntMMapA_empty(ima)); | |
261 | + assert(IntIntMMapA_size(ima) == 0); | |
262 | + assert(count == 0); | |
263 | + /* erase_range */ | |
264 | + for (i = 0; i < SIZE; i++) { | |
265 | + pos[i] = IntIntMMapA_insert(ima, hoge_int[i], hoge_int[i]); | |
266 | + assert(pos[i] && pos[i] != IntIntMMapA_end(ima)); | |
267 | + } | |
268 | + assert(IntIntMMapA_size(ima) == SIZE); | |
269 | + assert(IntIntMMapA_next(IntIntMMapA_find(ima, SIZE/2/2 -1)) == IntIntMMapA_erase_range(ima, IntIntMMapA_find(ima, 0), IntIntMMapA_next(IntIntMMapA_find(ima, SIZE/2/2 -1)))); | |
270 | + assert(IntIntMMapA_size(ima) == SIZE - SIZE/2/2); | |
271 | + assert(IntIntMMapA_end(ima) == IntIntMMapA_erase_range(ima, IntIntMMapA_begin(ima), IntIntMMapA_end(ima))); | |
272 | + assert(IntIntMMapA_size(ima) == 0); | |
273 | + assert(IntIntMMapA_insert(ima, hoge_int[0], hoge_int[0])); | |
274 | + assert(IntIntMMapA_size(ima) == 1); | |
275 | + assert(IntIntMMapA_next(IntIntMMapA_begin(ima)) == IntIntMMapA_erase_range(ima, IntIntMMapA_begin(ima), IntIntMMapA_next(IntIntMMapA_begin(ima)))); | |
276 | + assert(IntIntMMapA_size(ima) == 0); | |
277 | + assert(IntIntMMapA_insert(ima, 100, 100)); | |
278 | + assert(IntIntMMapA_insert(ima, 100, 100)); | |
279 | + assert(IntIntMMapA_insert(ima, 100, 100)); | |
280 | + assert(IntIntMMapA_insert(ima, 110, 110)); | |
281 | + assert(IntIntMMapA_insert(ima, 110, 110)); | |
282 | + assert(IntIntMMapA_size(ima) == 5); | |
283 | + assert(IntIntMMapA_upper_bound(ima, 110) == IntIntMMapA_erase_range(ima, IntIntMMapA_lower_bound(ima, 100), IntIntMMapA_upper_bound(ima, 110))); | |
284 | + assert(IntIntMMapA_size(ima) == 0); | |
285 | + /* erase_key */ | |
286 | + for (i = 0; i < SIZE; i++) { | |
287 | + pos[i] = IntIntMMapA_insert(ima, hoge_int[i], hoge_int[i]); | |
288 | + assert(pos[i] && pos[i] != IntIntMMapA_end(ima)); | |
289 | + } | |
290 | + assert(IntIntMMapA_size(ima) == SIZE); | |
291 | + for (i = 0; i < SIZE/2/2; i++) { | |
292 | + assert(IntIntMMapA_erase_key(ima, i) == 1); | |
293 | + } | |
294 | + assert(IntIntMMapA_size(ima) == SIZE - SIZE/2/2); | |
295 | + for (i = SIZE/2/2; i < SIZE/2; i++) { | |
296 | + assert(IntIntMMapA_erase_key(ima, i) == 3); | |
297 | + } | |
298 | + assert(IntIntMMapA_size(ima) == 0); | |
299 | + /* 大量にinsert */ | |
300 | + count = 0; | |
301 | + while (count < 1000000 && IntIntMMapA_insert(ima, 0, count)) { | |
302 | + count++; | |
303 | + } | |
304 | + assert(IntIntMMapA_size(ima) == count); | |
305 | + printf("count: %d\n", count); | |
306 | + | |
307 | + IntIntMMapA_delete(ima); | |
308 | +} | |
309 | + | |
310 | + | |
311 | + | |
312 | + | |
313 | + | |
314 | + | |
315 | + | |
316 | + | |
317 | + | |
318 | + | |
319 | + | |
320 | +void MapTest_run(void) | |
321 | +{ | |
322 | + printf("\n===== map test =====\n"); | |
323 | + map_init_hoge(); | |
324 | + | |
325 | + MapTest_test_1_1(); | |
326 | + MapTest_test_1_2(); | |
327 | +} | |
328 | + |
@@ -0,0 +1,38 @@ | ||
1 | +#include <stdio.h> | |
2 | +#include "../cstl/vector.h" | |
3 | + | |
4 | +VECTOR_INTERFACE(CharVector, char) | |
5 | +VECTOR_IMPLEMENT(CharVector, char) | |
6 | + | |
7 | +int main(void) | |
8 | +{ | |
9 | + CharVector *x = CharVector_new(); | |
10 | + CharVector_assign(x, "aaaa", 4); | |
11 | + CharVector_push_back(x, '\0'); | |
12 | + printf("%s\n", CharVector_at(x, 0)); | |
13 | + printf("size:%d\n", CharVector_size(x)); | |
14 | + | |
15 | + CharVector_pop_back(x); | |
16 | + CharVector_insert_n(x, CharVector_size(x), "bbbb", 4); | |
17 | + CharVector_push_back(x, '\0'); | |
18 | + printf("%s\n", CharVector_at(x, 0)); | |
19 | + printf("size:%d\n", CharVector_size(x)); | |
20 | + | |
21 | + *CharVector_at(x, 0) = 'c'; | |
22 | + *CharVector_at(x, 1) = 'd'; | |
23 | + *CharVector_at(x, 4) = 'e'; | |
24 | + *CharVector_at(x, 5) = 'f'; | |
25 | + printf("%s\n", CharVector_at(x, 0)); | |
26 | + | |
27 | + CharVector_erase_n(x, 2, 4); | |
28 | + printf("%s\n", CharVector_at(x, 0)); | |
29 | + | |
30 | + CharVector_insert(x, 0, 'g'); | |
31 | + CharVector_insert(x, 0, 'h'); | |
32 | + CharVector_insert(x, 0, 'i'); | |
33 | + CharVector_insert_n(x, 0, "jklm", 4); | |
34 | + printf("%s\n", CharVector_at(x, 0)); | |
35 | + | |
36 | + CharVector_delete(x); | |
37 | + return 0; | |
38 | +} |
@@ -0,0 +1,41 @@ | ||
1 | +#include <stdio.h> | |
2 | +#include "../cstl/deque.h" | |
3 | +#define NELEMS(array) (sizeof(array) / sizeof(array[0])) | |
4 | + | |
5 | +DEQUE_INTERFACE(UCharDeque, unsigned char) | |
6 | +DEQUE_IMPLEMENT(UCharDeque, unsigned char) | |
7 | + | |
8 | +int main(void) | |
9 | +{ | |
10 | + int i; | |
11 | + unsigned char buf[32]; | |
12 | + UCharDeque *x; | |
13 | + UCharDeque y; | |
14 | + | |
15 | + x = UCharDeque_new(31); | |
16 | + UCharDeque_push_back(x, 0x01); | |
17 | + UCharDeque_push_back(x, 0x02); | |
18 | + UCharDeque_push_front(x, 0x03); | |
19 | + UCharDeque_push_front(x, 0x04); | |
20 | + UCharDeque_insert(x, 1, 0x05); | |
21 | + UCharDeque_erase(x, 2); | |
22 | + *UCharDeque_at(x, 0) = 0x06; | |
23 | + for (i = 0; i < UCharDeque_size(x); i++) { | |
24 | + printf("%02x\n", *UCharDeque_at(x, i)); | |
25 | + } | |
26 | + while (!UCharDeque_empty(x)) { | |
27 | + printf("%02x\n", UCharDeque_pop_front(x)); | |
28 | + } | |
29 | + UCharDeque_delete(x); | |
30 | + | |
31 | + /* 呼び出し側で用意したオブジェクトとバッファを利用する場合 */ | |
32 | + UCharDeque_init(&y, buf, NELEMS(buf)); | |
33 | + UCharDeque_push_back(&y, 0x01); | |
34 | + UCharDeque_push_back(&y, 0x02); | |
35 | + while (!UCharDeque_empty(&y)) { | |
36 | + printf("%02x\n", UCharDeque_pop_front(&y)); | |
37 | + } | |
38 | + /* UCharDeque_delete(&y)を呼び出してはいけない */ | |
39 | + return 0; | |
40 | +} | |
41 | + |
@@ -0,0 +1,61 @@ | ||
1 | +/* C++標準ライブラリ チュートリアル&リファレンス | |
2 | + * Nicolai M. Josuttis著, 吉川邦夫訳, アスキー, 2001 | |
3 | + * p.450の例を移植 */ | |
4 | +#include <stdio.h> | |
5 | +#include "../cstl/string.h" | |
6 | + | |
7 | +STRING_INTERFACE(String, char) | |
8 | +STRING_IMPLEMENT(String, char) | |
9 | + | |
10 | +/* コマンドライン引数に.tmpという拡張子をつける | |
11 | + * 拡張子が付いていれば.tmpに変える | |
12 | + * 最初から.tmpという拡張子ならば.xxxという拡張子をつける */ | |
13 | +int main(int argc, char *argv[]) | |
14 | +{ | |
15 | + int i; | |
16 | + String *filename = String_new(); | |
17 | + String *basename = String_new(); | |
18 | + String *extname = String_new(); | |
19 | + String *tmpname = String_new(); | |
20 | + String *suffix = String_new_cstr("tmp", NPOS); | |
21 | + | |
22 | + for (i = 1; i < argc; i++) { | |
23 | + size_t idx; | |
24 | + /* コマンドライン引数をファイル名とする */ | |
25 | + String_assign(filename, argv[i], NPOS); | |
26 | + /* ファイル名から'.'を探す */ | |
27 | + idx = String_find_c(String_c_str(filename), '.', 0); | |
28 | + if (idx == NPOS) { | |
29 | + /* ファイル名に'.'が含まれない | |
30 | + * ".tmp"を追加 */ | |
31 | + String_assign(tmpname, String_c_str(filename), NPOS); | |
32 | + String_push_back(tmpname, '.'); | |
33 | + String_append(tmpname, String_c_str(suffix), NPOS); | |
34 | + } else { | |
35 | + /* ファイル名を基本名と拡張子に分ける */ | |
36 | + String_assign(basename, String_c_str(filename), idx); | |
37 | + String_assign(extname, String_c_str(filename) + idx+1, NPOS); | |
38 | + if (String_empty(extname)) { | |
39 | + /* '.'のあとに拡張子がない場合、"tmp"を付ける */ | |
40 | + String_assign(tmpname, String_c_str(filename), NPOS); | |
41 | + String_append(tmpname, String_c_str(suffix), NPOS); | |
42 | + } else if (String_compare(extname, suffix) == 0) { | |
43 | + /* "tmp"を"xxx"に置換 */ | |
44 | + String_assign(tmpname, String_c_str(filename), NPOS); | |
45 | + String_replace(tmpname, idx+1, String_size(extname), "xxx", NPOS); | |
46 | + } else { | |
47 | + /* その他の拡張子を"tmp"に置換 */ | |
48 | + String_assign(tmpname, String_c_str(filename), NPOS); | |
49 | + String_replace(tmpname, idx+1, NPOS, String_c_str(suffix), NPOS); | |
50 | + } | |
51 | + } | |
52 | + printf("%s => %s\n", String_c_str(filename), String_c_str(tmpname)); | |
53 | + } | |
54 | + | |
55 | + String_delete(filename); | |
56 | + String_delete(basename); | |
57 | + String_delete(extname); | |
58 | + String_delete(tmpname); | |
59 | + String_delete(suffix); | |
60 | + return 0; | |
61 | +} |
@@ -0,0 +1,46 @@ | ||
1 | +/* C++標準ライブラリ チュートリアル&リファレンス | |
2 | + * Nicolai M. Josuttis著, 吉川邦夫訳, アスキー, 2001 | |
3 | + * p.454の例を移植 */ | |
4 | +#include <stdio.h> | |
5 | +#include "../cstl/string.h" | |
6 | + | |
7 | +STRING_INTERFACE(String, char) | |
8 | +STRING_IMPLEMENT(String, char) | |
9 | + | |
10 | +/* 標準入力から個々の単語を抽出し、それぞれの文字を逆順に出力する */ | |
11 | +int main(int argc, char *argv[]) | |
12 | +{ | |
13 | + /* 区切り文字 */ | |
14 | + String *delims = String_new_cstr(" \t,.;", NPOS); | |
15 | + String *line = String_new(); | |
16 | + char buf[1024]; | |
17 | + | |
18 | + while (fgets(buf, 1024, stdin)) { | |
19 | + size_t begIdx, endIdx; | |
20 | + String_assign(line, buf, NPOS); | |
21 | + String_erase(line, String_length(line)-1, NPOS); /* '\n'を取り除く */ | |
22 | + /* 最初の単語の先頭を検索する */ | |
23 | + begIdx = String_find_first_not_of(String_c_str(line), String_c_str(delims), 0, NPOS); | |
24 | + /* 単語の先頭が見つかるまで繰り返す */ | |
25 | + while (begIdx != NPOS) { | |
26 | + size_t i; | |
27 | + /* 単語の末尾を検索する */ | |
28 | + endIdx = String_find_first_of(String_c_str(line), String_c_str(delims), begIdx, NPOS); | |
29 | + if (endIdx == NPOS) { | |
30 | + /* 単語の終わりは行末である */ | |
31 | + endIdx = String_length(line); | |
32 | + } | |
33 | + /* 単語の文字を逆順に出力する */ | |
34 | + for (i = endIdx; i > begIdx; --i) { | |
35 | + putchar(*String_at(line, i-1)); | |
36 | + } | |
37 | + putchar(' '); | |
38 | + /* 次の単語の先頭を検索する */ | |
39 | + begIdx = String_find_first_not_of(String_c_str(line), String_c_str(delims), endIdx, NPOS); | |
40 | + } | |
41 | + putchar('\n'); | |
42 | + } | |
43 | + String_delete(line); | |
44 | + String_delete(delims); | |
45 | + return 0; | |
46 | +} |
@@ -0,0 +1,55 @@ | ||
1 | +/* C++標準ライブラリ チュートリアル&リファレンス | |
2 | + * Nicolai M. Josuttis著, 吉川邦夫訳, アスキー, 2001 | |
3 | + * p.212の例を移植 */ | |
4 | +#include <stdio.h> | |
5 | +#include <string.h> | |
6 | +#include "../cstl/map.h" | |
7 | + | |
8 | +MULTIMAP_INTERFACE(StrStrMMap, char *, char *) | |
9 | +MULTIMAP_IMPLEMENT(StrStrMMap, char *, char *, strcmp, ASC) | |
10 | + | |
11 | +/* 辞書として使う */ | |
12 | +int main(void) | |
13 | +{ | |
14 | + StrStrMMapIterator pos; | |
15 | + StrStrMMap *dict = StrStrMMap_new(); | |
16 | + char *word; | |
17 | + | |
18 | + StrStrMMap_insert(dict , "day" , "Tag"); | |
19 | + StrStrMMap_insert(dict , "strange" , "fremd"); | |
20 | + StrStrMMap_insert(dict , "car" , "Auto"); | |
21 | + StrStrMMap_insert(dict , "smart" , "elegant"); | |
22 | + StrStrMMap_insert(dict , "trait" , "Merkmal"); | |
23 | + StrStrMMap_insert(dict , "strange" , "seltsam"); | |
24 | + StrStrMMap_insert(dict , "smart" , "raffiniert"); | |
25 | + StrStrMMap_insert(dict , "smart" , "klug"); | |
26 | + StrStrMMap_insert(dict , "clever" , "raffiniert"); | |
27 | + | |
28 | + /* すべての要素を出力する */ | |
29 | + printf("english\t\tgerman\n"); | |
30 | + printf("-------------------------------\n"); | |
31 | + for (pos = StrStrMMap_begin(dict); pos != StrStrMMap_end(dict); pos = StrStrMMap_next(pos)) { | |
32 | + printf("%s\t\t%s\n", StrStrMMap_key(pos), *StrStrMMap_value(pos)); | |
33 | + } | |
34 | + printf("\n"); | |
35 | + | |
36 | + /* "smart"というキーに対応するすべての値を出力する */ | |
37 | + word = "smart"; | |
38 | + printf("%s: \n", word); | |
39 | + for (pos = StrStrMMap_lower_bound(dict, word); pos != StrStrMMap_upper_bound(dict, word); pos = StrStrMMap_next(pos)) { | |
40 | + printf("\t%s\n", *StrStrMMap_value(pos)); | |
41 | + } | |
42 | + printf("\n"); | |
43 | + | |
44 | + /* "raffiniert"という値に対応するすべてのキーを出力する */ | |
45 | + word = "raffiniert"; | |
46 | + printf("%s: \n", word); | |
47 | + for (pos = StrStrMMap_begin(dict); pos != StrStrMMap_end(dict); pos = StrStrMMap_next(pos)) { | |
48 | + if (strcmp(word, *StrStrMMap_value(pos)) == 0) { | |
49 | + printf("\t%s\n", StrStrMMap_key(pos)); | |
50 | + } | |
51 | + } | |
52 | + | |
53 | + StrStrMMap_delete(dict); | |
54 | + return 0; | |
55 | +} |
@@ -0,0 +1,73 @@ | ||
1 | +#include <stdlib.h> | |
2 | +#include <stdio.h> | |
3 | +#include <string.h> | |
4 | +#include "../cstl/list.h" | |
5 | + | |
6 | +typedef struct Hoge_t { | |
7 | + char *key; | |
8 | + int value; | |
9 | +} Hoge; | |
10 | + | |
11 | +Hoge *Hoge_new(char *key, int value) | |
12 | +{ | |
13 | + Hoge *self = malloc(sizeof(Hoge)); | |
14 | + self->key = key; self->value = value; | |
15 | + return self; | |
16 | +} | |
17 | + | |
18 | +void Hoge_delete(Hoge *self) | |
19 | +{ | |
20 | + free(self); | |
21 | +} | |
22 | + | |
23 | +void Hoge_print(Hoge *self) | |
24 | +{ | |
25 | + printf("%s: %d\n", self->key, self->value); | |
26 | +} | |
27 | + | |
28 | +LIST_INTERFACE(HogeList, Hoge *) | |
29 | +LIST_IMPLEMENT(HogeList, Hoge *) | |
30 | + | |
31 | +int main(void) | |
32 | +{ | |
33 | + Hoge *hoge; | |
34 | + HogeListIterator pos; | |
35 | + HogeList *x = HogeList_new(); | |
36 | + | |
37 | + hoge = Hoge_new("aaa", 1); | |
38 | + HogeList_push_back(x, hoge); | |
39 | + hoge = Hoge_new("bbb", 2); | |
40 | + HogeList_push_back(x, hoge); | |
41 | + hoge = Hoge_new("ccc", 3); | |
42 | + HogeList_push_front(x, hoge); | |
43 | + hoge = Hoge_new("ddd", 4); | |
44 | + HogeList_push_front(x, hoge); | |
45 | + | |
46 | + for (pos = HogeList_begin(x); pos != HogeList_end(x); pos = HogeList_next(pos)) { | |
47 | + Hoge_print(*HogeList_at(pos)); | |
48 | + } | |
49 | + for (pos = HogeList_begin(x); pos != HogeList_end(x); pos = HogeList_next(pos)) { | |
50 | + Hoge *h = *HogeList_at(pos); | |
51 | + if (!strcmp(h->key, "bbb")) { | |
52 | + hoge = Hoge_new("eee", 5); | |
53 | + HogeList_insert(x, pos, hoge); | |
54 | + } | |
55 | + } | |
56 | + for (pos = HogeList_begin(x); pos != HogeList_end(x);) { | |
57 | + Hoge *h = *HogeList_at(pos); | |
58 | + if (!strcmp(h->key, "bbb")) { | |
59 | + pos = HogeList_erase(x, pos); | |
60 | + Hoge_delete(h); | |
61 | + } else { | |
62 | + pos = HogeList_next(pos); | |
63 | + } | |
64 | + } | |
65 | + while (!HogeList_empty(x)) { | |
66 | + Hoge *h = HogeList_pop_front(x); | |
67 | + Hoge_print(h); | |
68 | + Hoge_delete(h); | |
69 | + } | |
70 | + HogeList_delete(x); | |
71 | + return 0; | |
72 | +} | |
73 | + |
@@ -0,0 +1,49 @@ | ||
1 | +#include <stdio.h> | |
2 | +#include "../cstl/set.h" | |
3 | + | |
4 | +SET_INTERFACE(IntSet, int) | |
5 | +SET_IMPLEMENT(IntSet, int, SIMPLE_CMP, ASC) | |
6 | + | |
7 | +int main(void) | |
8 | +{ | |
9 | + int success; | |
10 | + IntSetIterator pos; | |
11 | + IntSet *x = IntSet_new(); | |
12 | + | |
13 | + IntSet_insert(x, 4, NULL); | |
14 | + IntSet_insert(x, 3, NULL); | |
15 | + IntSet_insert(x, 5, NULL); | |
16 | + IntSet_insert(x, 1, NULL); | |
17 | + IntSet_insert(x, 6, NULL); | |
18 | + IntSet_insert(x, 2, NULL); | |
19 | + IntSet_insert(x, 5, NULL); | |
20 | + IntSet_insert(x, 8, NULL); | |
21 | + IntSet_insert(x, 7, NULL); | |
22 | + | |
23 | + for (pos = IntSet_begin(x); pos != IntSet_end(x); pos = IntSet_next(pos)) { | |
24 | + printf("%d ", IntSet_key(pos)); | |
25 | + } | |
26 | + printf("\n"); | |
27 | + | |
28 | + IntSet_insert(x, 4, &success); | |
29 | + if (success) { | |
30 | + printf("4 inserted as element\n"); | |
31 | + } else { | |
32 | + printf("4 already exists\n"); | |
33 | + } | |
34 | + | |
35 | + IntSet_erase_range(x, IntSet_begin(x), IntSet_find(x, 3)); | |
36 | + IntSet_erase_key(x, 5); | |
37 | + | |
38 | + for (pos = IntSet_begin(x); pos != IntSet_end(x); pos = IntSet_next(pos)) { | |
39 | + printf("%d ", IntSet_key(pos)); | |
40 | + } | |
41 | + printf("\n"); | |
42 | + | |
43 | + printf("lower_bound(5): %d\n", IntSet_key(IntSet_lower_bound(x, 5))); | |
44 | + printf("upper_bound(5): %d\n", IntSet_key(IntSet_upper_bound(x, 5))); | |
45 | + printf("lower_bound(6): %d\n", IntSet_key(IntSet_lower_bound(x, 6))); | |
46 | + printf("upper_bound(6): %d\n", IntSet_key(IntSet_upper_bound(x, 6))); | |
47 | + IntSet_delete(x); | |
48 | + return 0; | |
49 | +} |
@@ -0,0 +1,53 @@ | ||
1 | +/* C++標準ライブラリ チュートリアル&リファレンス | |
2 | + * Nicolai M. Josuttis著, 吉川邦夫訳, アスキー, 2001 | |
3 | + * p.211の例を移植 */ | |
4 | +#include <stdio.h> | |
5 | +#include <string.h> | |
6 | +#include "../cstl/map.h" | |
7 | + | |
8 | +MAP_INTERFACE(StrFltMap, char *, float) | |
9 | +MAP_IMPLEMENT(StrFltMap, char *, float, strcmp, ASC) | |
10 | + | |
11 | +/* 連想配列として使う */ | |
12 | +int main(void) | |
13 | +{ | |
14 | + StrFltMapIterator pos; | |
15 | + StrFltMap *stocks = StrFltMap_new(); | |
16 | + | |
17 | + /* 要素の挿入 */ | |
18 | + *StrFltMap_lookup(stocks, "BASF") = 369.50; | |
19 | + *StrFltMap_lookup(stocks, "VW") = 413.50; | |
20 | + *StrFltMap_lookup(stocks, "Daimler") = 819.00; | |
21 | + *StrFltMap_lookup(stocks, "BMW") = 834.00; | |
22 | + *StrFltMap_lookup(stocks, "Siemens") = 842.20; | |
23 | + | |
24 | + /* すべての要素を出力する */ | |
25 | + for (pos = StrFltMap_begin(stocks); pos != StrFltMap_end(stocks); pos = StrFltMap_next(pos)) { | |
26 | + printf("stock: %s\tprice: %g\n", StrFltMap_key(pos), *StrFltMap_value(pos)); | |
27 | + } | |
28 | + printf("\n"); | |
29 | + | |
30 | + /* 値が倍になった */ | |
31 | + for (pos = StrFltMap_begin(stocks); pos != StrFltMap_end(stocks); pos = StrFltMap_next(pos)) { | |
32 | + *StrFltMap_value(pos) *= 2; | |
33 | + } | |
34 | + /* すべての要素を出力する */ | |
35 | + for (pos = StrFltMap_begin(stocks); pos != StrFltMap_end(stocks); pos = StrFltMap_next(pos)) { | |
36 | + printf("stock: %s\tprice: %g\n", StrFltMap_key(pos), *StrFltMap_value(pos)); | |
37 | + } | |
38 | + printf("\n"); | |
39 | + | |
40 | + /* キーの"VW"を"Volkswagen"に変更する | |
41 | + * キーは変更不可なので値をコピーして古いキーを削除するしかない */ | |
42 | + *StrFltMap_lookup(stocks, "Volkswagen") = *StrFltMap_lookup(stocks, "VW"); | |
43 | + StrFltMap_erase_key(stocks, "VW"); | |
44 | + | |
45 | + /* すべての要素を出力する */ | |
46 | + for (pos = StrFltMap_begin(stocks); pos != StrFltMap_end(stocks); pos = StrFltMap_next(pos)) { | |
47 | + printf("stock: %s\tprice: %g\n", StrFltMap_key(pos), *StrFltMap_value(pos)); | |
48 | + } | |
49 | + printf("\n"); | |
50 | + | |
51 | + StrFltMap_delete(stocks); | |
52 | + return 0; | |
53 | +} |
@@ -0,0 +1,143 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2006, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file heap.h | |
27 | + * \brief 動的メモリの確保と解放 | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2006-03-22 | |
30 | + * | |
31 | + * 必要ならば排他制御をすること。 | |
32 | + * | |
33 | + * \par 使用例 | |
34 | + * | |
35 | + * \code | |
36 | + * #include "heap.h" | |
37 | + * Heap heap; | |
38 | + * char buf[1024]; | |
39 | + * #define malloc(s) Heap_alloc(&heap, s) | |
40 | + * #define realloc(p, s) Heap_realloc(&heap, p, s) | |
41 | + * #define free(p) Heap_free(&heap, p) | |
42 | + * | |
43 | + * int main(void) | |
44 | + * { | |
45 | + * int i; | |
46 | + * char *hoge; | |
47 | + * Heap_init(&heap, buf, sizeof buf); | |
48 | + * hoge = Heap_alloc(&heap, 16); | |
49 | + * for (i = 0; i < 16; i++) { | |
50 | + * hoge[i] = i; | |
51 | + * } | |
52 | + * Heap_free(&heap, hoge); | |
53 | + * | |
54 | + * hoge = malloc(64); | |
55 | + * for (i = 0; i < 64; i++) { | |
56 | + * hoge[i] = i; | |
57 | + * } | |
58 | + * hoge = realloc(hoge, 128); | |
59 | + * for (i = 64; i < 128; i++) { | |
60 | + * hoge[i] = i; | |
61 | + * } | |
62 | + * free(hoge); | |
63 | + * | |
64 | + * DUMP_MEMORY_LEAK(&heap, 1); | |
65 | + * return 0; | |
66 | + * } | |
67 | + * \endcode | |
68 | + */ | |
69 | +#ifndef HEAP_H_INCLUDED | |
70 | +#define HEAP_H_INCLUDED | |
71 | + | |
72 | +#include <stddef.h> | |
73 | + | |
74 | +/* | |
75 | + * SLIST_BLOCKをプリプロセッサシンボル定義した場合、メモリブロックのリストが | |
76 | + * 単方向リストとなる。メモリブロックヘッダのサイズがポインタ一つ分小さくな | |
77 | + * り、freeの計算量がO(n)になる。 | |
78 | + * SLIST_BLOCKを定義しない場合、メモリブロックのリストが双方向リストとなる。 | |
79 | + * メモリブロックヘッダのサイズがポインタ一つ分大きくなり、freeの計算量が | |
80 | + * O(1)になる。 | |
81 | + */ | |
82 | +/*#define SLIST_BLOCK*/ | |
83 | + | |
84 | +/*! | |
85 | + * \brief メモリブロックヘッダ構造体 | |
86 | + */ | |
87 | +typedef struct BlockHeader_t BlockHeader; | |
88 | +struct BlockHeader_t { | |
89 | +#ifndef SLIST_BLOCK | |
90 | + BlockHeader *prev; | |
91 | +#endif | |
92 | + BlockHeader *next; | |
93 | + size_t size; /* ブロックのサイズ(ヘッダのサイズも含む) */ | |
94 | + unsigned char occupied; /* 使用中フラグ */ | |
95 | + unsigned char magic; /* マジックナンバー */ | |
96 | +#ifdef HEAP_DEBUG | |
97 | + char *file; | |
98 | + size_t line; | |
99 | +#endif | |
100 | +}; | |
101 | + | |
102 | +/*! | |
103 | + * \brief ヒープ構造体 | |
104 | + * | |
105 | + * メモリブロックヘッダのリストを持つ | |
106 | + */ | |
107 | +typedef struct Heap_t Heap; | |
108 | +struct Heap_t { | |
109 | + BlockHeader list_term; /* メモリブロックリストターミネータ */ | |
110 | + BlockHeader *loop_p; /* ループ用ポインタ */ | |
111 | + void *init_flag; | |
112 | +}; | |
113 | + | |
114 | +#ifdef __cplusplus | |
115 | +extern "C" { | |
116 | +#endif | |
117 | +void Heap_init(Heap *self, void *buf, size_t size); | |
118 | +void Heap_free(Heap *self, void *ptr); | |
119 | +#ifdef HEAP_DEBUG | |
120 | +void *Heap_alloc_debug(Heap *self, size_t size, char *file, size_t line); | |
121 | +void *Heap_realloc_debug(Heap *self, void *ptr, size_t newsize, char *file, size_t line); | |
122 | +void hex_dump(void *buf, size_t size); | |
123 | +size_t dump_memory_leak(Heap *self, int dump); | |
124 | +void dump_memory_block(Heap *self, void *ptr); | |
125 | +void dump_memory_list(Heap *self); | |
126 | +#define Heap_alloc(h, s) Heap_alloc_debug(h, s, __FILE__, __LINE__) | |
127 | +#define Heap_realloc(h, p, s) Heap_realloc_debug(h, p, s, __FILE__, __LINE__) | |
128 | +#define DUMP_MEMORY_LEAK(h, d) dump_memory_leak(h, d) | |
129 | +#define DUMP_MEMORY_BLOCK(h, p) dump_memory_block(h, p) | |
130 | +#define DUMP_MEMORY_LIST(h) dump_memory_list(h) | |
131 | +#else | |
132 | +void *Heap_alloc(Heap *self, size_t size); | |
133 | +void *Heap_realloc(Heap *self, void *ptr, size_t newsize); | |
134 | +#define DUMP_MEMORY_LEAK(h, d) | |
135 | +#define DUMP_MEMORY_BLOCK(h, p) | |
136 | +#define DUMP_MEMORY_LIST(h) | |
137 | +#endif | |
138 | +#ifdef __cplusplus | |
139 | +} | |
140 | +#endif | |
141 | + | |
142 | + | |
143 | +#endif /* HEAP_H_INCLUDED */ |
@@ -0,0 +1,192 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2006, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file set.h | |
27 | + * \brief set/multisetコンテナ | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2006-11-11 | |
30 | + */ | |
31 | +#ifndef CSTL_SET_H_INCLUDED | |
32 | +#define CSTL_SET_H_INCLUDED | |
33 | + | |
34 | +#include "rbtree.h" | |
35 | + | |
36 | +#ifdef __cplusplus | |
37 | +#define SET_BEGIN_EXTERN_C() extern "C" { | |
38 | +#define SET_END_EXTERN_C() } | |
39 | +#else | |
40 | +#define SET_BEGIN_EXTERN_C() | |
41 | +#define SET_END_EXTERN_C() | |
42 | +#endif | |
43 | + | |
44 | + | |
45 | +#define COMMON_SET_IMPLEMENT(Name, Type, Compare, Order) \ | |
46 | +/*! | |
47 | + * \brief setノード構造体 | |
48 | + */\ | |
49 | +struct Name##RBTreeNode_t {\ | |
50 | + struct Name##RBTreeNode_t *parent;\ | |
51 | + struct Name##RBTreeNode_t *left;\ | |
52 | + struct Name##RBTreeNode_t *right;\ | |
53 | + RBTreeColor color;\ | |
54 | + Type key;\ | |
55 | +};\ | |
56 | +\ | |
57 | +RBTREE_WRAPPER_IMPLEMENT(Name, Type, Type, Compare, Order)\ | |
58 | +\ | |
59 | +static Name##RBTreeNode *Name##RBTreeNode_new(Type elem, Type value, RBTreeColor color)\ | |
60 | +{\ | |
61 | + Name##RBTreeNode *self;\ | |
62 | + self = (Name##RBTreeNode *) malloc(sizeof(Name##RBTreeNode));\ | |
63 | + if (!self) return 0;\ | |
64 | + self->key = elem;\ | |
65 | + self->left = &Name##RBTree_nil;\ | |
66 | + self->right = &Name##RBTree_nil;\ | |
67 | + self->parent = &Name##RBTree_nil;\ | |
68 | + self->color = color;\ | |
69 | + return self;\ | |
70 | +}\ | |
71 | +\ | |
72 | + | |
73 | + | |
74 | +/*! | |
75 | + * \brief インターフェイスマクロ | |
76 | + * | |
77 | + * \param Name コンテナ名 | |
78 | + * \param Type 要素の型 | |
79 | + */ | |
80 | +#define SET_INTERFACE(Name, Type) \ | |
81 | +\ | |
82 | +SET_BEGIN_EXTERN_C()\ | |
83 | +RBTREE_WRAPPER_INTERFACE(Name, Type, Type)\ | |
84 | +Name##Iterator Name##_insert(Name *self, Type elem, int *success);\ | |
85 | +SET_END_EXTERN_C()\ | |
86 | + | |
87 | +/*! | |
88 | + * \brief 実装マクロ | |
89 | + * | |
90 | + * \param Name コンテナ名 | |
91 | + * \param Type 要素の型 | |
92 | + * \param Compare 要素の比較ルーチン | |
93 | + * \param Order ソートの順序 | |
94 | + */ | |
95 | +#define SET_IMPLEMENT(Name, Type, Compare, Order) \ | |
96 | +COMMON_SET_IMPLEMENT(Name, Type, Compare, Order)\ | |
97 | +\ | |
98 | +Name *Name##_new_copy(Name *x)\ | |
99 | +{\ | |
100 | + Name##Iterator pos;\ | |
101 | + Name *self;\ | |
102 | + assert(x && "Set_new_copy");\ | |
103 | + assert(x->magic == x && "Set_new_copy");\ | |
104 | + self = Name##_new();\ | |
105 | + if (!self) return 0;\ | |
106 | + for (pos = Name##_begin(x); pos != Name##_end(x); pos = Name##_next(pos)) {\ | |
107 | + if (!Name##_insert(self, Name##_key(pos), 0)) {\ | |
108 | + Name##_delete(self);\ | |
109 | + return 0;\ | |
110 | + }\ | |
111 | + }\ | |
112 | + return self;\ | |
113 | +}\ | |
114 | +\ | |
115 | +Name##Iterator Name##_insert(Name *self, Type elem, int *success)\ | |
116 | +{\ | |
117 | + Name##Iterator pos;\ | |
118 | + assert(self && "Set_insert");\ | |
119 | + assert(self->magic == self && "Set_insert");\ | |
120 | + pos = Name##RBTree_find(self->tree, elem);\ | |
121 | + if (pos == Name##RBTree_end(self->tree)) {\ | |
122 | + pos = Name##RBTree_insert(self->tree, elem, elem);\ | |
123 | + if (pos) {\ | |
124 | + if (success) *success = 1;\ | |
125 | + self->nelems++;\ | |
126 | + } else {\ | |
127 | + if (success) *success = 0;\ | |
128 | + }\ | |
129 | + } else {\ | |
130 | + if (success) *success = 0;\ | |
131 | + }\ | |
132 | + return pos;\ | |
133 | +}\ | |
134 | +\ | |
135 | + | |
136 | + | |
137 | +/*! | |
138 | + * \brief インターフェイスマクロ | |
139 | + * | |
140 | + * \param Name コンテナ名 | |
141 | + * \param Type 要素の型 | |
142 | + */ | |
143 | +#define MULTISET_INTERFACE(Name, Type) \ | |
144 | +\ | |
145 | +SET_BEGIN_EXTERN_C()\ | |
146 | +RBTREE_WRAPPER_INTERFACE(Name, Type, Type)\ | |
147 | +Name##Iterator Name##_insert(Name *self, Type elem);\ | |
148 | +SET_END_EXTERN_C()\ | |
149 | + | |
150 | +/*! | |
151 | + * \brief 実装マクロ | |
152 | + * | |
153 | + * \param Name コンテナ名 | |
154 | + * \param Type 要素の型 | |
155 | + * \param Compare 要素の比較ルーチン | |
156 | + * \param Order ソートの順序 | |
157 | + */ | |
158 | +#define MULTISET_IMPLEMENT(Name, Type, Compare, Order) \ | |
159 | +COMMON_SET_IMPLEMENT(Name, Type, Compare, Order)\ | |
160 | +\ | |
161 | +Name *Name##_new_copy(Name *x)\ | |
162 | +{\ | |
163 | + Name##Iterator pos;\ | |
164 | + Name *self;\ | |
165 | + assert(x && "Set_new_copy");\ | |
166 | + assert(x->magic == x && "Set_new_copy");\ | |
167 | + self = Name##_new();\ | |
168 | + if (!self) return 0;\ | |
169 | + for (pos = Name##_begin(x); pos != Name##_end(x); pos = Name##_next(pos)) {\ | |
170 | + if (!Name##_insert(self, Name##_key(pos))) {\ | |
171 | + Name##_delete(self);\ | |
172 | + return 0;\ | |
173 | + }\ | |
174 | + }\ | |
175 | + return self;\ | |
176 | +}\ | |
177 | +\ | |
178 | +Name##Iterator Name##_insert(Name *self, Type elem)\ | |
179 | +{\ | |
180 | + Name##Iterator pos;\ | |
181 | + assert(self && "MultiSet_insert");\ | |
182 | + assert(self->magic == self && "MultiSet_insert");\ | |
183 | + pos = Name##RBTree_insert(self->tree, elem, elem);\ | |
184 | + if (pos) {\ | |
185 | + self->nelems++;\ | |
186 | + }\ | |
187 | + return pos;\ | |
188 | +}\ | |
189 | +\ | |
190 | + | |
191 | + | |
192 | +#endif /* CSTL_SET_H_INCLUDED */ |
@@ -0,0 +1,389 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2006, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file list.h | |
27 | + * \brief listコンテナ | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2006-02-26 | |
30 | + */ | |
31 | +#ifndef CSTL_LIST_H_INCLUDED | |
32 | +#define CSTL_LIST_H_INCLUDED | |
33 | + | |
34 | +#include <stddef.h> | |
35 | +#include <stdlib.h> | |
36 | +#include <assert.h> | |
37 | + | |
38 | +#ifdef __cplusplus | |
39 | +#define LIST_BEGIN_EXTERN_C() extern "C" { | |
40 | +#define LIST_END_EXTERN_C() } | |
41 | +#else | |
42 | +#define LIST_BEGIN_EXTERN_C() | |
43 | +#define LIST_END_EXTERN_C() | |
44 | +#endif | |
45 | + | |
46 | +#ifndef NDEBUG | |
47 | +#define LIST_MAGIC(x) x | |
48 | +#else | |
49 | +#define LIST_MAGIC(x) | |
50 | +#endif | |
51 | + | |
52 | +/*! | |
53 | + * \brief インターフェイスマクロ | |
54 | + * | |
55 | + * \param Name コンテナ名 | |
56 | + * \param Type 要素の型 | |
57 | + */ | |
58 | +#define LIST_INTERFACE(Name, Type) \ | |
59 | +typedef struct Name##Node_t Name##Node;\ | |
60 | +typedef struct Name##_t Name;\ | |
61 | +/*! | |
62 | + * \brief イテレータ | |
63 | + */\ | |
64 | +typedef Name##Node *Name##Iterator;\ | |
65 | +\ | |
66 | +LIST_BEGIN_EXTERN_C()\ | |
67 | +Name *Name##_new(void);\ | |
68 | +Name *Name##_new_copy(Name *x);\ | |
69 | +void Name##_delete(Name *self);\ | |
70 | +int Name##_assign(Name *self, Type *elems, size_t n);\ | |
71 | +int Name##_push_back(Name *self, Type elem);\ | |
72 | +int Name##_push_front(Name *self, Type elem);\ | |
73 | +Type Name##_pop_front(Name *self);\ | |
74 | +Type Name##_pop_back(Name *self);\ | |
75 | +int Name##_empty(Name *self);\ | |
76 | +size_t Name##_size(Name *self);\ | |
77 | +void Name##_clear(Name *self);\ | |
78 | +Type *Name##_at(Name##Iterator pos);\ | |
79 | +Type Name##_front(Name *self);\ | |
80 | +Type Name##_back(Name *self);\ | |
81 | +Name##Iterator Name##_begin(Name *self);\ | |
82 | +Name##Iterator Name##_end(Name *self);\ | |
83 | +Name##Iterator Name##_rbegin(Name *self);\ | |
84 | +Name##Iterator Name##_rend(Name *self);\ | |
85 | +Name##Iterator Name##_next(Name##Iterator pos);\ | |
86 | +Name##Iterator Name##_prev(Name##Iterator pos);\ | |
87 | +Name##Iterator Name##_insert(Name *self, Name##Iterator pos, Type elem);\ | |
88 | +Name##Iterator Name##_erase(Name *self, Name##Iterator pos);\ | |
89 | +Name##Iterator Name##_erase_range(Name *self, Name##Iterator first, Name##Iterator last);\ | |
90 | +int Name##_resize(Name *self, size_t n, Type elem);\ | |
91 | +LIST_END_EXTERN_C()\ | |
92 | + | |
93 | + | |
94 | +/*! | |
95 | + * \brief 実装マクロ | |
96 | + * | |
97 | + * \param Name コンテナ名 | |
98 | + * \param Type 要素の型 | |
99 | + */ | |
100 | +#define LIST_IMPLEMENT(Name, Type) \ | |
101 | +/*! | |
102 | + * \brief listノード構造体 | |
103 | + */\ | |
104 | +struct Name##Node_t {\ | |
105 | + Name##Node *prev;\ | |
106 | + Name##Node *next;\ | |
107 | + Type elem;\ | |
108 | +};\ | |
109 | +\ | |
110 | +/*! | |
111 | + * \brief list構造体 | |
112 | + */\ | |
113 | +struct Name##_t {\ | |
114 | + Name##Node terminator;\ | |
115 | + size_t nelems;\ | |
116 | + LIST_MAGIC(void *magic;)\ | |
117 | +};\ | |
118 | +\ | |
119 | +Name *Name##_new(void)\ | |
120 | +{\ | |
121 | + Name *self = (Name *) malloc(sizeof(Name));\ | |
122 | + if (!self) return 0;\ | |
123 | + self->terminator.next = &self->terminator;\ | |
124 | + self->terminator.prev = &self->terminator;\ | |
125 | + self->nelems = 0;\ | |
126 | + LIST_MAGIC(self->magic = self);\ | |
127 | + return self;\ | |
128 | +}\ | |
129 | +\ | |
130 | +Name *Name##_new_copy(Name *x)\ | |
131 | +{\ | |
132 | + Name##Iterator pos;\ | |
133 | + Name *self;\ | |
134 | + assert(x && "List_new_copy");\ | |
135 | + assert(x->magic == x && "List_new_copy");\ | |
136 | + self = Name##_new();\ | |
137 | + if (!self) return 0;\ | |
138 | + for (pos = Name##_begin(x); pos != Name##_end(x); pos = Name##_next(pos)) {\ | |
139 | + if (!Name##_push_back(self, *Name##_at(pos))) {\ | |
140 | + Name##_delete(self);\ | |
141 | + return 0;\ | |
142 | + }\ | |
143 | + }\ | |
144 | + return self;\ | |
145 | +}\ | |
146 | +\ | |
147 | +void Name##_delete(Name *self)\ | |
148 | +{\ | |
149 | + assert(self && "List_delete");\ | |
150 | + assert(self->magic == self && "List_delete");\ | |
151 | + Name##_clear(self);\ | |
152 | + LIST_MAGIC(self->magic = 0);\ | |
153 | + free(self);\ | |
154 | +}\ | |
155 | +\ | |
156 | +int Name##_assign(Name *self, Type *elems, size_t n)\ | |
157 | +{\ | |
158 | + size_t i;\ | |
159 | + assert(self && "List_assign");\ | |
160 | + assert(self->magic == self && "List_assign");\ | |
161 | + assert(elems && "List_assign");\ | |
162 | + Name##_clear(self);\ | |
163 | + for (i = 0; i < n; i++) {\ | |
164 | + if (!Name##_push_back(self, elems[i])) return 0;\ | |
165 | + }\ | |
166 | + return 1;\ | |
167 | +}\ | |
168 | +\ | |
169 | +int Name##_push_back(Name *self, Type elem)\ | |
170 | +{\ | |
171 | + Name##Node *node;\ | |
172 | + assert(self && "List_push_back");\ | |
173 | + assert(self->magic == self && "List_push_back");\ | |
174 | + node = (Name##Node *) malloc(sizeof(Name##Node));\ | |
175 | + if (!node) return 0;\ | |
176 | + node->elem = elem;\ | |
177 | + node->next = &self->terminator;\ | |
178 | + node->prev = self->terminator.prev;\ | |
179 | + self->terminator.prev->next = node;\ | |
180 | + self->terminator.prev = node;\ | |
181 | + self->nelems++;\ | |
182 | + return 1;\ | |
183 | +}\ | |
184 | +\ | |
185 | +int Name##_push_front(Name *self, Type elem)\ | |
186 | +{\ | |
187 | + Name##Node *node;\ | |
188 | + assert(self && "List_push_front");\ | |
189 | + assert(self->magic == self && "List_push_front");\ | |
190 | + node = (Name##Node *) malloc(sizeof(Name##Node));\ | |
191 | + if (!node) return 0;\ | |
192 | + node->elem = elem;\ | |
193 | + node->next = self->terminator.next;\ | |
194 | + node->prev = &self->terminator;\ | |
195 | + self->terminator.next->prev = node;\ | |
196 | + self->terminator.next = node;\ | |
197 | + self->nelems++;\ | |
198 | + return 1;\ | |
199 | +}\ | |
200 | +\ | |
201 | +Type Name##_pop_front(Name *self)\ | |
202 | +{\ | |
203 | + Name##Node *node;\ | |
204 | + Type elem;\ | |
205 | + assert(self && "List_pop_front");\ | |
206 | + assert(self->magic == self && "List_pop_front");\ | |
207 | + assert(!Name##_empty(self) && "List_pop_front");\ | |
208 | + node = self->terminator.next;\ | |
209 | + elem = node->elem;\ | |
210 | + if (node != &self->terminator) {\ | |
211 | + self->terminator.next = node->next;\ | |
212 | + node->next->prev = &self->terminator;\ | |
213 | + free(node);\ | |
214 | + self->nelems--;\ | |
215 | + }\ | |
216 | + return elem;\ | |
217 | +}\ | |
218 | +\ | |
219 | +Type Name##_pop_back(Name *self)\ | |
220 | +{\ | |
221 | + Name##Node *node;\ | |
222 | + Type elem;\ | |
223 | + assert(self && "List_pop_back");\ | |
224 | + assert(self->magic == self && "List_pop_back");\ | |
225 | + assert(!Name##_empty(self) && "List_pop_back");\ | |
226 | + node = self->terminator.prev;\ | |
227 | + elem = node->elem;\ | |
228 | + if (node != &self->terminator) {\ | |
229 | + self->terminator.prev = node->prev;\ | |
230 | + node->prev->next = &self->terminator;\ | |
231 | + free(node);\ | |
232 | + self->nelems--;\ | |
233 | + }\ | |
234 | + return elem;\ | |
235 | +}\ | |
236 | +\ | |
237 | +int Name##_empty(Name *self)\ | |
238 | +{\ | |
239 | + assert(self && "List_empty");\ | |
240 | + assert(self->magic == self && "List_empty");\ | |
241 | + return self->terminator.next == &self->terminator;\ | |
242 | +}\ | |
243 | +\ | |
244 | +size_t Name##_size(Name *self)\ | |
245 | +{\ | |
246 | + assert(self && "List_size");\ | |
247 | + assert(self->magic == self && "List_size");\ | |
248 | + return self->nelems;\ | |
249 | +}\ | |
250 | +\ | |
251 | +void Name##_clear(Name *self)\ | |
252 | +{\ | |
253 | + assert(self && "List_clear");\ | |
254 | + assert(self->magic == self && "List_clear");\ | |
255 | + while (self->nelems) {\ | |
256 | + Name##_pop_front(self);\ | |
257 | + }\ | |
258 | +}\ | |
259 | +\ | |
260 | +Type *Name##_at(Name##Iterator pos)\ | |
261 | +{\ | |
262 | + assert(pos && "List_at");\ | |
263 | + return &pos->elem;\ | |
264 | +}\ | |
265 | +\ | |
266 | +Type Name##_front(Name *self)\ | |
267 | +{\ | |
268 | + assert(self && "List_front");\ | |
269 | + assert(self->magic == self && "List_front");\ | |
270 | + assert(!Name##_empty(self) && "List_front");\ | |
271 | + return self->terminator.next->elem;\ | |
272 | +}\ | |
273 | +\ | |
274 | +Type Name##_back(Name *self)\ | |
275 | +{\ | |
276 | + assert(self && "List_back");\ | |
277 | + assert(self->magic == self && "List_back");\ | |
278 | + assert(!Name##_empty(self) && "List_back");\ | |
279 | + return self->terminator.prev->elem;\ | |
280 | +}\ | |
281 | +\ | |
282 | +Name##Iterator Name##_begin(Name *self)\ | |
283 | +{\ | |
284 | + assert(self && "List_begin");\ | |
285 | + assert(self->magic == self && "List_begin");\ | |
286 | + return self->terminator.next;\ | |
287 | +}\ | |
288 | +\ | |
289 | +Name##Iterator Name##_end(Name *self)\ | |
290 | +{\ | |
291 | + assert(self && "List_end");\ | |
292 | + assert(self->magic == self && "List_end");\ | |
293 | + return &self->terminator;\ | |
294 | +}\ | |
295 | +\ | |
296 | +Name##Iterator Name##_rbegin(Name *self)\ | |
297 | +{\ | |
298 | + assert(self && "List_rbegin");\ | |
299 | + assert(self->magic == self && "List_rbegin");\ | |
300 | + return self->terminator.prev;\ | |
301 | +}\ | |
302 | +\ | |
303 | +Name##Iterator Name##_rend(Name *self)\ | |
304 | +{\ | |
305 | + assert(self && "List_rend");\ | |
306 | + assert(self->magic == self && "List_rend");\ | |
307 | + return &self->terminator;\ | |
308 | +}\ | |
309 | +\ | |
310 | +Name##Iterator Name##_next(Name##Iterator pos)\ | |
311 | +{\ | |
312 | + assert(pos && "List_next");\ | |
313 | + return pos->next;\ | |
314 | +}\ | |
315 | +\ | |
316 | +Name##Iterator Name##_prev(Name##Iterator pos)\ | |
317 | +{\ | |
318 | + assert(pos && "List_prev");\ | |
319 | + return pos->prev;\ | |
320 | +}\ | |
321 | +\ | |
322 | +Name##Iterator Name##_insert(Name *self, Name##Iterator pos, Type elem)\ | |
323 | +{\ | |
324 | + Name##Node *node;\ | |
325 | + assert(self && "List_insert");\ | |
326 | + assert(self->magic == self && "List_insert");\ | |
327 | + assert(pos && "List_insert");\ | |
328 | + node = (Name##Node *) malloc(sizeof(Name##Node));\ | |
329 | + if (!node) return 0;\ | |
330 | + node->elem = elem;\ | |
331 | + node->next = pos;\ | |
332 | + node->prev = pos->prev;\ | |
333 | + pos->prev = node;\ | |
334 | + node->prev->next = node;\ | |
335 | + self->nelems++;\ | |
336 | + return node;\ | |
337 | +}\ | |
338 | +\ | |
339 | +Name##Iterator Name##_erase(Name *self, Name##Iterator pos)\ | |
340 | +{\ | |
341 | + Name##Node *node;\ | |
342 | + assert(self && "List_erase");\ | |
343 | + assert(self->magic == self && "List_erase");\ | |
344 | + assert(pos && "List_erase");\ | |
345 | + assert(pos != &self->terminator && "List_erase");\ | |
346 | + node = pos->next;\ | |
347 | + pos->prev->next = pos->next;\ | |
348 | + pos->next->prev = pos->prev;\ | |
349 | + free(pos);\ | |
350 | + self->nelems--;\ | |
351 | + return node;\ | |
352 | +}\ | |
353 | +\ | |
354 | +Name##Iterator Name##_erase_range(Name *self, Name##Iterator first, Name##Iterator last)\ | |
355 | +{\ | |
356 | + Name##Iterator pos;\ | |
357 | + assert(self && "List_erase_range");\ | |
358 | + assert(self->magic == self && "List_erase_range");\ | |
359 | + assert(first && "List_erase_range");\ | |
360 | + assert(last && "List_erase_range");\ | |
361 | + pos = first;\ | |
362 | + while (pos != last) {\ | |
363 | + pos = Name##_erase(self, pos);\ | |
364 | + }\ | |
365 | + return pos;\ | |
366 | +}\ | |
367 | +\ | |
368 | +int Name##_resize(Name *self, size_t n, Type elem)\ | |
369 | +{\ | |
370 | + size_t i;\ | |
371 | + size_t size;\ | |
372 | + assert(self && "List_resize");\ | |
373 | + assert(self->magic == self && "List_resize");\ | |
374 | + size = Name##_size(self);\ | |
375 | + if (size >= n) {\ | |
376 | + for (i = 0; i < size - n; i++) {\ | |
377 | + Name##_pop_back(self);\ | |
378 | + }\ | |
379 | + } else {\ | |
380 | + for (i = 0; i < n - size; i++) {\ | |
381 | + if (!Name##_push_back(self, elem)) return 0;\ | |
382 | + }\ | |
383 | + }\ | |
384 | + return 1;\ | |
385 | +}\ | |
386 | +\ | |
387 | + | |
388 | + | |
389 | +#endif /* CSTL_LIST_H_INCLUDED */ |
@@ -0,0 +1,228 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2006, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file map.h | |
27 | + * \brief map/multimapコンテナ | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2006-11-11 | |
30 | + */ | |
31 | +#ifndef CSTL_MAP_H_INCLUDED | |
32 | +#define CSTL_MAP_H_INCLUDED | |
33 | + | |
34 | +#include "rbtree.h" | |
35 | + | |
36 | +#ifdef __cplusplus | |
37 | +#define MAP_BEGIN_EXTERN_C() extern "C" { | |
38 | +#define MAP_END_EXTERN_C() } | |
39 | +#else | |
40 | +#define MAP_BEGIN_EXTERN_C() | |
41 | +#define MAP_END_EXTERN_C() | |
42 | +#endif | |
43 | + | |
44 | + | |
45 | +#define COMMON_MAP_IMPLEMENT(Name, KeyType, ValueType, Compare, Order) \ | |
46 | +/*! | |
47 | + * \brief mapノード構造体 | |
48 | + */\ | |
49 | +struct Name##RBTreeNode_t {\ | |
50 | + struct Name##RBTreeNode_t *parent;\ | |
51 | + struct Name##RBTreeNode_t *left;\ | |
52 | + struct Name##RBTreeNode_t *right;\ | |
53 | + RBTreeColor color;\ | |
54 | + KeyType key;\ | |
55 | + ValueType value;\ | |
56 | +};\ | |
57 | +\ | |
58 | +RBTREE_WRAPPER_IMPLEMENT(Name, KeyType, ValueType, Compare, Order)\ | |
59 | +\ | |
60 | +static Name##RBTreeNode *Name##RBTreeNode_new(KeyType key, ValueType value, RBTreeColor color)\ | |
61 | +{\ | |
62 | + Name##RBTreeNode *self;\ | |
63 | + self = (Name##RBTreeNode *) malloc(sizeof(Name##RBTreeNode));\ | |
64 | + if (!self) return 0;\ | |
65 | + self->key = key;\ | |
66 | + self->value = value;\ | |
67 | + self->left = &Name##RBTree_nil;\ | |
68 | + self->right = &Name##RBTree_nil;\ | |
69 | + self->parent = &Name##RBTree_nil;\ | |
70 | + self->color = color;\ | |
71 | + return self;\ | |
72 | +}\ | |
73 | +\ | |
74 | +ValueType *Name##_value(Name##Iterator pos)\ | |
75 | +{\ | |
76 | + assert(pos && "Map_value");\ | |
77 | + assert(!Name##RBTreeNode_is_head(pos) && "Map_value");\ | |
78 | + return &pos->value;\ | |
79 | +}\ | |
80 | +\ | |
81 | + | |
82 | + | |
83 | +/*! | |
84 | + * \brief インターフェイスマクロ | |
85 | + * | |
86 | + * \param Name コンテナ名 | |
87 | + * \param KeyType 要素のキーの型 | |
88 | + * \param ValueType 要素の値の型 | |
89 | + */ | |
90 | +#define MAP_INTERFACE(Name, KeyType, ValueType) \ | |
91 | +MAP_BEGIN_EXTERN_C()\ | |
92 | +RBTREE_WRAPPER_INTERFACE(Name, KeyType, ValueType)\ | |
93 | +Name##Iterator Name##_insert(Name *self, KeyType key, ValueType value, int *success);\ | |
94 | +ValueType *Name##_value(Name##Iterator pos);\ | |
95 | +ValueType *Name##_lookup(Name *self, KeyType key);\ | |
96 | +MAP_END_EXTERN_C()\ | |
97 | + | |
98 | +/*! | |
99 | + * \brief 実装マクロ | |
100 | + * | |
101 | + * \param Name コンテナ名 | |
102 | + * \param KeyType 要素のキーの型 | |
103 | + * \param ValueType 要素の値の型 | |
104 | + * \param Compare 要素の比較ルーチン | |
105 | + * \param Order ソートの順序 | |
106 | + */ | |
107 | +#define MAP_IMPLEMENT(Name, KeyType, ValueType, Compare, Order) \ | |
108 | +\ | |
109 | +COMMON_MAP_IMPLEMENT(Name, KeyType, ValueType, Compare, Order) \ | |
110 | +\ | |
111 | +Name *Name##_new_copy(Name *x)\ | |
112 | +{\ | |
113 | + Name##Iterator pos;\ | |
114 | + Name *self;\ | |
115 | + assert(x && "Map_new_copy");\ | |
116 | + assert(x->magic == x && "Map_new_copy");\ | |
117 | + self = Name##_new();\ | |
118 | + if (!self) return 0;\ | |
119 | + for (pos = Name##_begin(x); pos != Name##_end(x); pos = Name##_next(pos)) {\ | |
120 | + if (!Name##_insert(self, Name##_key(pos), *Name##_value(pos), 0)) {\ | |
121 | + Name##_delete(self);\ | |
122 | + return 0;\ | |
123 | + }\ | |
124 | + }\ | |
125 | + return self;\ | |
126 | +}\ | |
127 | +\ | |
128 | +Name##Iterator Name##_insert(Name *self, KeyType key, ValueType value, int *success)\ | |
129 | +{\ | |
130 | + Name##Iterator pos;\ | |
131 | + assert(self && "Map_insert");\ | |
132 | + assert(self->magic == self && "Map_insert");\ | |
133 | + pos = Name##RBTree_find(self->tree, key);\ | |
134 | + if (pos == Name##RBTree_end(self->tree)) {\ | |
135 | + pos = Name##RBTree_insert(self->tree, key, value);\ | |
136 | + if (pos) {\ | |
137 | + if (success) *success = 1;\ | |
138 | + self->nelems++;\ | |
139 | + } else {\ | |
140 | + if (success) *success = 0;\ | |
141 | + }\ | |
142 | + } else {\ | |
143 | + if (success) *success = 0;\ | |
144 | + }\ | |
145 | + return pos;\ | |
146 | +}\ | |
147 | +\ | |
148 | +ValueType *Name##_lookup(Name *self, KeyType key)\ | |
149 | +{\ | |
150 | + Name##Iterator pos;\ | |
151 | + assert(self && "Map_lookup");\ | |
152 | + assert(self->magic == self && "Map_lookup");\ | |
153 | + pos = Name##RBTree_find(self->tree, key);\ | |
154 | + if (pos == Name##RBTree_end(self->tree)) {\ | |
155 | + static ValueType value; /* 新しい要素の値 */\ | |
156 | + pos = Name##RBTree_insert(self->tree, key, value);\ | |
157 | + if (pos) {\ | |
158 | + self->nelems++;\ | |
159 | + } else {\ | |
160 | + /* メモリ不足 */\ | |
161 | + assert(0 && "Map_lookup");\ | |
162 | + return 0;\ | |
163 | + }\ | |
164 | + }\ | |
165 | + return &pos->value;\ | |
166 | +}\ | |
167 | +\ | |
168 | + | |
169 | + | |
170 | +/*! | |
171 | + * \brief インターフェイスマクロ | |
172 | + * | |
173 | + * \param Name コンテナ名 | |
174 | + * \param KeyType 要素のキーの型 | |
175 | + * \param ValueType 要素の値の型 | |
176 | + */ | |
177 | +#define MULTIMAP_INTERFACE(Name, KeyType, ValueType) \ | |
178 | +MAP_BEGIN_EXTERN_C()\ | |
179 | +RBTREE_WRAPPER_INTERFACE(Name, KeyType, ValueType)\ | |
180 | +Name##Iterator Name##_insert(Name *self, KeyType key, ValueType value);\ | |
181 | +ValueType *Name##_value(Name##Iterator pos);\ | |
182 | +MAP_END_EXTERN_C()\ | |
183 | + | |
184 | +/*! | |
185 | + * \brief 実装マクロ | |
186 | + * | |
187 | + * \param Name コンテナ名 | |
188 | + * \param KeyType 要素のキーの型 | |
189 | + * \param ValueType 要素の値の型 | |
190 | + * \param Compare 要素の比較ルーチン | |
191 | + * \param Order ソートの順序 | |
192 | + */ | |
193 | +#define MULTIMAP_IMPLEMENT(Name, KeyType, ValueType, Compare, Order) \ | |
194 | +\ | |
195 | +COMMON_MAP_IMPLEMENT(Name, KeyType, ValueType, Compare, Order) \ | |
196 | +\ | |
197 | +Name *Name##_new_copy(Name *x)\ | |
198 | +{\ | |
199 | + Name##Iterator pos;\ | |
200 | + Name *self;\ | |
201 | + assert(x && "Map_new_copy");\ | |
202 | + assert(x->magic == x && "Map_new_copy");\ | |
203 | + self = Name##_new();\ | |
204 | + if (!self) return 0;\ | |
205 | + for (pos = Name##_begin(x); pos != Name##_end(x); pos = Name##_next(pos)) {\ | |
206 | + if (!Name##_insert(self, Name##_key(pos), *Name##_value(pos))) {\ | |
207 | + Name##_delete(self);\ | |
208 | + return 0;\ | |
209 | + }\ | |
210 | + }\ | |
211 | + return self;\ | |
212 | +}\ | |
213 | +\ | |
214 | +Name##Iterator Name##_insert(Name *self, KeyType key, ValueType value)\ | |
215 | +{\ | |
216 | + Name##Iterator pos;\ | |
217 | + assert(self && "MultiMap_insert");\ | |
218 | + assert(self->magic == self && "MultiMap_insert");\ | |
219 | + pos = Name##RBTree_insert(self->tree, key, value);\ | |
220 | + if (pos) {\ | |
221 | + self->nelems++;\ | |
222 | + }\ | |
223 | + return pos;\ | |
224 | +}\ | |
225 | +\ | |
226 | + | |
227 | + | |
228 | +#endif /* CSTL_MAP_H_INCLUDED */ |
@@ -0,0 +1,359 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2006, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file vector.h | |
27 | + * \brief vectorコンテナ | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2006-11-29 | |
30 | + */ | |
31 | +#ifndef CSTL_VECTOR_H_INCLUDED | |
32 | +#define CSTL_VECTOR_H_INCLUDED | |
33 | + | |
34 | +#include <stddef.h> | |
35 | +#include <stdlib.h> | |
36 | +#include <assert.h> | |
37 | + | |
38 | +#ifdef __cplusplus | |
39 | +#define VECTOR_BEGIN_EXTERN_C() extern "C" { | |
40 | +#define VECTOR_END_EXTERN_C() } | |
41 | +#else | |
42 | +#define VECTOR_BEGIN_EXTERN_C() | |
43 | +#define VECTOR_END_EXTERN_C() | |
44 | +#endif | |
45 | + | |
46 | +#ifndef NDEBUG | |
47 | +#define VECTOR_MAGIC(x) x | |
48 | +#else | |
49 | +#define VECTOR_MAGIC(x) | |
50 | +#endif | |
51 | + | |
52 | +#define VECTOR_INIT_SIZE 16 | |
53 | + | |
54 | +/*! | |
55 | + * \brief インターフェイスマクロ | |
56 | + * | |
57 | + * \param Name コンテナ名 | |
58 | + * \param Type 要素の型 | |
59 | + */ | |
60 | +#define VECTOR_INTERFACE(Name, Type) \ | |
61 | +typedef struct Name##_t Name;\ | |
62 | +\ | |
63 | +VECTOR_BEGIN_EXTERN_C()\ | |
64 | +Name *Name##_new(void);\ | |
65 | +Name *Name##_new_copy(Name *x);\ | |
66 | +void Name##_delete(Name *self);\ | |
67 | +int Name##_assign(Name *self, Type *elems, size_t n);\ | |
68 | +int Name##_push_back(Name *self, Type elem);\ | |
69 | +Type Name##_pop_back(Name *self);\ | |
70 | +size_t Name##_size(Name *self);\ | |
71 | +size_t Name##_capacity(Name *self);\ | |
72 | +int Name##_empty(Name *self);\ | |
73 | +void Name##_clear(Name *self);\ | |
74 | +int Name##_reserve(Name *self, size_t n);\ | |
75 | +void Name##_shrink(Name *self, size_t n);\ | |
76 | +int Name##_resize(Name *self, size_t n, Type elem);\ | |
77 | +Type *Name##_at(Name *self, size_t idx);\ | |
78 | +Type Name##_front(Name *self);\ | |
79 | +Type Name##_back(Name *self);\ | |
80 | +int Name##_insert(Name *self, size_t idx, Type elem);\ | |
81 | +int Name##_insert_n(Name *self, size_t idx, Type *elems, size_t n);\ | |
82 | +void Name##_erase(Name *self, size_t idx);\ | |
83 | +void Name##_erase_n(Name *self, size_t idx, size_t n);\ | |
84 | +VECTOR_END_EXTERN_C()\ | |
85 | + | |
86 | + | |
87 | +/*! | |
88 | + * \brief 実装マクロ | |
89 | + * | |
90 | + * \param Name コンテナ名 | |
91 | + * \param Type 要素の型 | |
92 | + */ | |
93 | +#define VECTOR_IMPLEMENT(Name, Type) \ | |
94 | +/*! | |
95 | + * \brief vector構造体 | |
96 | + */\ | |
97 | +struct Name##_t {\ | |
98 | + size_t end;\ | |
99 | + size_t nelems;\ | |
100 | + Type *buf;\ | |
101 | + VECTOR_MAGIC(void *magic;)\ | |
102 | +};\ | |
103 | +\ | |
104 | +static int Name##_full(Name *self)\ | |
105 | +{\ | |
106 | + return (Name##_size(self) == Name##_capacity(self));\ | |
107 | +}\ | |
108 | +\ | |
109 | +static int Name##_expand(Name *self, size_t size)\ | |
110 | +{\ | |
111 | + size_t n;\ | |
112 | + n = (size > Name##_capacity(self) * 2) ? size : Name##_capacity(self) * 2;\ | |
113 | + return Name##_reserve(self, n);\ | |
114 | +}\ | |
115 | +\ | |
116 | +static Name *Name##_new_reserve(size_t n)\ | |
117 | +{\ | |
118 | + Name *self;\ | |
119 | + Type *buf;\ | |
120 | + self = (Name *) malloc(sizeof(Name));\ | |
121 | + if (!self) return 0;\ | |
122 | + buf = (Type *) malloc(sizeof(Type) * (n+1));\ | |
123 | + if (!buf) {\ | |
124 | + free(self);\ | |
125 | + return 0;\ | |
126 | + }\ | |
127 | + self->end = 0;\ | |
128 | + self->buf = buf;\ | |
129 | + self->nelems = n+1;\ | |
130 | + VECTOR_MAGIC(self->magic = self);\ | |
131 | + return self;\ | |
132 | +}\ | |
133 | +\ | |
134 | +Name *Name##_new(void)\ | |
135 | +{\ | |
136 | + return Name##_new_reserve(VECTOR_INIT_SIZE-1);\ | |
137 | +}\ | |
138 | +\ | |
139 | +Name *Name##_new_copy(Name *x)\ | |
140 | +{\ | |
141 | + Name *self;\ | |
142 | + assert(x && "Vector_new_copy");\ | |
143 | + assert(x->magic == x && "Vector_new_copy");\ | |
144 | + self = Name##_new_reserve(Name##_size(x));\ | |
145 | + if (!self) return 0;\ | |
146 | + Name##_insert_n(self, 0, Name##_at(x, 0), Name##_size(x));\ | |
147 | + return self;\ | |
148 | +}\ | |
149 | +\ | |
150 | +void Name##_delete(Name *self)\ | |
151 | +{\ | |
152 | + assert(self && "Vector_delete");\ | |
153 | + assert(self->magic == self && "Vector_delete");\ | |
154 | + VECTOR_MAGIC(self->magic = 0);\ | |
155 | + free(self->buf);\ | |
156 | + free(self);\ | |
157 | +}\ | |
158 | +\ | |
159 | +int Name##_assign(Name *self, Type *elems, size_t n)\ | |
160 | +{\ | |
161 | + size_t i;\ | |
162 | + assert(self && "Vector_assign");\ | |
163 | + assert(self->magic == self && "Vector_assign");\ | |
164 | + assert(elems && "Vector_assign");\ | |
165 | + if (n > Name##_capacity(self)) {\ | |
166 | + if (!Name##_expand(self, Name##_capacity(self) + n)) return 0;\ | |
167 | + }\ | |
168 | + for (i = 0; i < n; i++) {\ | |
169 | + self->buf[i] = elems[i];\ | |
170 | + }\ | |
171 | + self->end = n;\ | |
172 | + return 1;\ | |
173 | +}\ | |
174 | +\ | |
175 | +int Name##_push_back(Name *self, Type elem)\ | |
176 | +{\ | |
177 | + assert(self && "Vector_push_back");\ | |
178 | + assert(self->magic == self && "Vector_push_back");\ | |
179 | + if (Name##_full(self)) {\ | |
180 | + if (!Name##_expand(self, Name##_capacity(self) + 1)) return 0;\ | |
181 | + }\ | |
182 | + self->buf[self->end] = elem;\ | |
183 | + self->end++;\ | |
184 | + return 1;\ | |
185 | +}\ | |
186 | +\ | |
187 | +Type Name##_pop_back(Name *self)\ | |
188 | +{\ | |
189 | + assert(self && "Vector_pop_back");\ | |
190 | + assert(self->magic == self && "Vector_pop_back");\ | |
191 | + assert(!Name##_empty(self) && "Vector_pop_back");\ | |
192 | + if (!Name##_empty(self)) {\ | |
193 | + self->end--;\ | |
194 | + }\ | |
195 | + return self->buf[self->end];\ | |
196 | +}\ | |
197 | +\ | |
198 | +size_t Name##_size(Name *self)\ | |
199 | +{\ | |
200 | + assert(self && "Vector_size");\ | |
201 | + assert(self->magic == self && "Vector_size");\ | |
202 | + return self->end;\ | |
203 | +}\ | |
204 | +\ | |
205 | +size_t Name##_capacity(Name *self)\ | |
206 | +{\ | |
207 | + assert(self && "Vector_capacity");\ | |
208 | + assert(self->magic == self && "Vector_capacity");\ | |
209 | + return (self->nelems - 1);\ | |
210 | +}\ | |
211 | +\ | |
212 | +int Name##_empty(Name *self)\ | |
213 | +{\ | |
214 | + assert(self && "Vector_empty");\ | |
215 | + assert(self->magic == self && "Vector_empty");\ | |
216 | + return (self->end == 0);\ | |
217 | +}\ | |
218 | +\ | |
219 | +void Name##_clear(Name *self)\ | |
220 | +{\ | |
221 | + assert(self && "Vector_clear");\ | |
222 | + assert(self->magic == self && "Vector_clear");\ | |
223 | + self->end = 0;\ | |
224 | +}\ | |
225 | +\ | |
226 | +int Name##_reserve(Name *self, size_t n)\ | |
227 | +{\ | |
228 | + Type *newbuf;\ | |
229 | + assert(self && "Vector_reserve");\ | |
230 | + assert(self->magic == self && "Vector_reserve");\ | |
231 | + if (n <= Name##_capacity(self)) return 1;\ | |
232 | + newbuf = (Type *) realloc(self->buf, sizeof(Type) * (n+1));\ | |
233 | + if (!newbuf) return 0;\ | |
234 | + self->buf = newbuf;\ | |
235 | + self->nelems = n+1;\ | |
236 | + return 1;\ | |
237 | +}\ | |
238 | +\ | |
239 | +void Name##_shrink(Name *self, size_t n)\ | |
240 | +{\ | |
241 | + Type *newbuf;\ | |
242 | + assert(self && "Vector_shrink");\ | |
243 | + assert(self->magic == self && "Vector_shrink");\ | |
244 | + if (n >= Name##_capacity(self)) return;\ | |
245 | + if (n < Name##_size(self)) {\ | |
246 | + n = Name##_size(self);\ | |
247 | + }\ | |
248 | + newbuf = (Type *) realloc(self->buf, sizeof(Type) * (n+1));\ | |
249 | + if (newbuf) {\ | |
250 | + self->buf = newbuf;\ | |
251 | + }\ | |
252 | + self->nelems = n+1;\ | |
253 | +}\ | |
254 | +\ | |
255 | +int Name##_resize(Name *self, size_t n, Type elem)\ | |
256 | +{\ | |
257 | + size_t size;\ | |
258 | + assert(self && "Vector_resize");\ | |
259 | + assert(self->magic == self && "Vector_resize");\ | |
260 | + size = Name##_size(self);\ | |
261 | + if (size >= n) {\ | |
262 | + self->end = n;\ | |
263 | + } else {\ | |
264 | + size_t i;\ | |
265 | + if (!Name##_reserve(self, n)) {\ | |
266 | + return 0;\ | |
267 | + }\ | |
268 | + for (i = 0; i < n - size; i++) {\ | |
269 | + Name##_push_back(self, elem);\ | |
270 | + }\ | |
271 | + }\ | |
272 | + return 1;\ | |
273 | +}\ | |
274 | +\ | |
275 | +Type *Name##_at(Name *self, size_t idx)\ | |
276 | +{\ | |
277 | + assert(self && "Vector_at");\ | |
278 | + assert(self->magic == self && "Vector_at");\ | |
279 | + assert(Name##_size(self) > idx && "Vector_at");\ | |
280 | + return &self->buf[idx];\ | |
281 | +}\ | |
282 | +\ | |
283 | +Type Name##_front(Name *self)\ | |
284 | +{\ | |
285 | + assert(self && "Vector_front");\ | |
286 | + assert(self->magic == self && "Vector_front");\ | |
287 | + assert(!Name##_empty(self) && "Vector_front");\ | |
288 | + return self->buf[0];\ | |
289 | +}\ | |
290 | +\ | |
291 | +Type Name##_back(Name *self)\ | |
292 | +{\ | |
293 | + assert(self && "Vector_back");\ | |
294 | + assert(self->magic == self && "Vector_back");\ | |
295 | + assert(!Name##_empty(self) && "Vector_back");\ | |
296 | + return self->buf[self->end - 1];\ | |
297 | +}\ | |
298 | +\ | |
299 | +static void Name##_move_forward(Name *self, size_t first, size_t last, size_t n)\ | |
300 | +{\ | |
301 | + int i;\ | |
302 | + for (i = (int)last - 1; i > (int)first - 1; i--) {\ | |
303 | + self->buf[i+n] = self->buf[i];\ | |
304 | + }\ | |
305 | +}\ | |
306 | +\ | |
307 | +static void Name##_move_backward(Name *self, size_t first, size_t last, size_t n)\ | |
308 | +{\ | |
309 | + size_t i;\ | |
310 | + for (i = first; i < last; i++) {\ | |
311 | + self->buf[i-n] = self->buf[i];\ | |
312 | + }\ | |
313 | +}\ | |
314 | +\ | |
315 | +int Name##_insert(Name *self, size_t idx, Type elem)\ | |
316 | +{\ | |
317 | + assert(self && "Vector_insert");\ | |
318 | + assert(self->magic == self && "Vector_insert");\ | |
319 | + assert(Name##_size(self) >= idx && "Vector_insert");\ | |
320 | + return Name##_insert_n(self, idx, &elem, 1);\ | |
321 | +}\ | |
322 | +\ | |
323 | +int Name##_insert_n(Name *self, size_t idx, Type *elems, size_t n)\ | |
324 | +{\ | |
325 | + size_t i, j;\ | |
326 | + assert(self && "Vector_insert_n");\ | |
327 | + assert(self->magic == self && "Vector_insert_n");\ | |
328 | + assert(Name##_size(self) >= idx && "Vector_insert_n");\ | |
329 | + assert(elems && "Vector_insert_n");\ | |
330 | + if (Name##_size(self) + n > Name##_capacity(self)) {\ | |
331 | + if (!Name##_expand(self, Name##_capacity(self) + n)) return 0;\ | |
332 | + }\ | |
333 | + Name##_move_forward(self, idx, self->end, n);\ | |
334 | + self->end += n;\ | |
335 | + for (i = idx, j = 0; j < n; i++, j++) {\ | |
336 | + self->buf[i] = elems[j];\ | |
337 | + }\ | |
338 | + return 1;\ | |
339 | +}\ | |
340 | +\ | |
341 | +void Name##_erase(Name *self, size_t idx)\ | |
342 | +{\ | |
343 | + assert(self && "Vector_erase");\ | |
344 | + assert(self->magic == self && "Vector_erase");\ | |
345 | + assert(Name##_size(self) >= idx + 1 && "Vector_erase");\ | |
346 | + Name##_erase_n(self, idx, 1);\ | |
347 | +}\ | |
348 | +\ | |
349 | +void Name##_erase_n(Name *self, size_t idx, size_t n)\ | |
350 | +{\ | |
351 | + assert(self && "Vector_erase_n");\ | |
352 | + assert(self->magic == self && "Vector_erase_n");\ | |
353 | + assert(Name##_size(self) >= idx + n && "Vector_erase_n");\ | |
354 | + Name##_move_backward(self, idx + n, self->end, n);\ | |
355 | + self->end -= n;\ | |
356 | +}\ | |
357 | +\ | |
358 | + | |
359 | +#endif /* CSTL_VECTOR_H_INCLUDED */ |
@@ -0,0 +1,396 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2006, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file deque.h | |
27 | + * \brief dequeコンテナ | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2006-02-25 | |
30 | + */ | |
31 | +#ifndef CSTL_DEQUE_H_INCLUDED | |
32 | +#define CSTL_DEQUE_H_INCLUDED | |
33 | + | |
34 | +#include <stddef.h> | |
35 | +#include <stdlib.h> | |
36 | +#include <assert.h> | |
37 | + | |
38 | +#ifdef __cplusplus | |
39 | +#define DEQUE_BEGIN_EXTERN_C() extern "C" { | |
40 | +#define DEQUE_END_EXTERN_C() } | |
41 | +#else | |
42 | +#define DEQUE_BEGIN_EXTERN_C() | |
43 | +#define DEQUE_END_EXTERN_C() | |
44 | +#endif | |
45 | + | |
46 | +#ifndef NDEBUG | |
47 | +#define DEQUE_MAGIC(x) x | |
48 | +#else | |
49 | +#define DEQUE_MAGIC(x) | |
50 | +#endif | |
51 | + | |
52 | +/*! | |
53 | + * \brief インターフェイスマクロ | |
54 | + * | |
55 | + * \param Name コンテナ名 | |
56 | + * \param Type 要素の型 | |
57 | + */ | |
58 | +#define DEQUE_INTERFACE(Name, Type) \ | |
59 | +typedef struct Name##_t Name;\ | |
60 | +/*! | |
61 | + * \brief deque構造体 | |
62 | + */\ | |
63 | +struct Name##_t {\ | |
64 | + size_t begin;\ | |
65 | + size_t end;\ | |
66 | + size_t nelems;\ | |
67 | + Type *buf;\ | |
68 | + DEQUE_MAGIC(void *magic;)\ | |
69 | +};\ | |
70 | +\ | |
71 | +DEQUE_BEGIN_EXTERN_C()\ | |
72 | +Name *Name##_new(size_t n);\ | |
73 | +Name *Name##_new_copy(Name *x);\ | |
74 | +void Name##_init(Name *self, Type *buf, size_t n);\ | |
75 | +void Name##_delete(Name *self);\ | |
76 | +int Name##_assign(Name *self, Type *elems, size_t n);\ | |
77 | +int Name##_push_back(Name *self, Type elem);\ | |
78 | +int Name##_push_front(Name *self, Type elem);\ | |
79 | +Type Name##_pop_front(Name *self);\ | |
80 | +Type Name##_pop_back(Name *self);\ | |
81 | +size_t Name##_size(Name *self);\ | |
82 | +size_t Name##_max_size(Name *self);\ | |
83 | +int Name##_empty(Name *self);\ | |
84 | +int Name##_full(Name *self);\ | |
85 | +void Name##_clear(Name *self);\ | |
86 | +Type *Name##_at(Name *self, size_t idx);\ | |
87 | +Type Name##_front(Name *self);\ | |
88 | +Type Name##_back(Name *self);\ | |
89 | +int Name##_insert(Name *self, size_t idx, Type elem);\ | |
90 | +int Name##_insert_n(Name *self, size_t idx, Type *elems, size_t n);\ | |
91 | +void Name##_erase(Name *self, size_t idx);\ | |
92 | +void Name##_erase_n(Name *self, size_t idx, size_t n);\ | |
93 | +int Name##_resize(Name *self, size_t n, Type elem);\ | |
94 | +DEQUE_END_EXTERN_C()\ | |
95 | + | |
96 | + | |
97 | +/*! | |
98 | + * \brief 実装マクロ | |
99 | + * | |
100 | + * \param Name コンテナ名 | |
101 | + * \param Type 要素の型 | |
102 | + */ | |
103 | +#define DEQUE_IMPLEMENT(Name, Type) \ | |
104 | +\ | |
105 | +static size_t Name##_forward(Name *self, size_t idx, size_t n)\ | |
106 | +{\ | |
107 | + return (idx + n) % self->nelems;\ | |
108 | +}\ | |
109 | +\ | |
110 | +static size_t Name##_backward(Name *self, size_t idx, size_t n)\ | |
111 | +{\ | |
112 | + int tmp = idx - n;\ | |
113 | + return (tmp >= 0) ? tmp : self->nelems + tmp;\ | |
114 | +}\ | |
115 | +\ | |
116 | +static size_t Name##_next(Name *self, size_t idx)\ | |
117 | +{\ | |
118 | + return Name##_forward(self, idx, 1);\ | |
119 | +}\ | |
120 | +\ | |
121 | +static size_t Name##_prev(Name *self, size_t idx)\ | |
122 | +{\ | |
123 | + return Name##_backward(self, idx, 1);\ | |
124 | +}\ | |
125 | +\ | |
126 | +static size_t Name##_distance(Name *self, size_t first, size_t last)\ | |
127 | +{\ | |
128 | + return (first <= last) ? last - first : self->nelems - first + last;\ | |
129 | +}\ | |
130 | +\ | |
131 | +Name *Name##_new(size_t n)\ | |
132 | +{\ | |
133 | + Name *self;\ | |
134 | + Type *buf;\ | |
135 | + if (!n) return 0;\ | |
136 | + self = (Name *) malloc(sizeof(Name));\ | |
137 | + if (!self) return 0;\ | |
138 | + buf = (Type *) malloc(sizeof(Type) * (n+1));\ | |
139 | + if (!buf) {\ | |
140 | + free(self);\ | |
141 | + return 0;\ | |
142 | + }\ | |
143 | + Name##_init(self, buf, (n+1));\ | |
144 | + return self;\ | |
145 | +}\ | |
146 | +\ | |
147 | +Name *Name##_new_copy(Name *x)\ | |
148 | +{\ | |
149 | + Name *self;\ | |
150 | + assert(x && "Deque_new_copy");\ | |
151 | + assert(x->magic == x && "Deque_new_copy");\ | |
152 | + self = Name##_new(Name##_max_size(x));\ | |
153 | + if (!self) return 0;\ | |
154 | + Name##_insert_n(self, 0, Name##_at(x, 0), Name##_size(x));\ | |
155 | + return self;\ | |
156 | +}\ | |
157 | +\ | |
158 | +void Name##_delete(Name *self)\ | |
159 | +{\ | |
160 | + assert(self && "Deque_delete");\ | |
161 | + assert(self->magic == self && "Deque_delete");\ | |
162 | + DEQUE_MAGIC(self->magic = 0);\ | |
163 | + free(self->buf);\ | |
164 | + free(self);\ | |
165 | +}\ | |
166 | +\ | |
167 | +void Name##_init(Name *self, Type *buf, size_t n)\ | |
168 | +{\ | |
169 | + assert(self && "Deque_init");\ | |
170 | + assert(buf && "Deque_init");\ | |
171 | + self->begin = 0;\ | |
172 | + self->end = 0;\ | |
173 | + self->buf = buf;\ | |
174 | + self->nelems = n;\ | |
175 | + DEQUE_MAGIC(self->magic = self);\ | |
176 | +}\ | |
177 | +\ | |
178 | +int Name##_assign(Name *self, Type *elems, size_t n)\ | |
179 | +{\ | |
180 | + size_t i;\ | |
181 | + assert(self && "Deque_assign");\ | |
182 | + assert(self->magic == self && "Deque_assign");\ | |
183 | + assert(elems && "Deque_assign");\ | |
184 | + if (n > Name##_max_size(self)) return 0;\ | |
185 | + for (i = 0; i < n; i++) {\ | |
186 | + self->buf[i] = elems[i];\ | |
187 | + }\ | |
188 | + self->begin = 0;\ | |
189 | + self->end = n;\ | |
190 | + return 1;\ | |
191 | +}\ | |
192 | +\ | |
193 | +int Name##_push_back(Name *self, Type elem)\ | |
194 | +{\ | |
195 | + assert(self && "Deque_push_back");\ | |
196 | + assert(self->magic == self && "Deque_push_back");\ | |
197 | + if (Name##_full(self)) return 0;\ | |
198 | + self->buf[self->end] = elem;\ | |
199 | + self->end = Name##_next(self, self->end);\ | |
200 | + return 1;\ | |
201 | +}\ | |
202 | +\ | |
203 | +int Name##_push_front(Name *self, Type elem)\ | |
204 | +{\ | |
205 | + assert(self && "Deque_push_front");\ | |
206 | + assert(self->magic == self && "Deque_push_front");\ | |
207 | + if (Name##_full(self)) return 0;\ | |
208 | + self->begin = Name##_prev(self, self->begin);\ | |
209 | + self->buf[self->begin] = elem;\ | |
210 | + return 1;\ | |
211 | +}\ | |
212 | +\ | |
213 | +Type Name##_pop_front(Name *self)\ | |
214 | +{\ | |
215 | + Type elem;\ | |
216 | + assert(self && "Deque_pop_front");\ | |
217 | + assert(self->magic == self && "Deque_pop_front");\ | |
218 | + assert(!Name##_empty(self) && "Deque_pop_front");\ | |
219 | + elem = self->buf[self->begin];\ | |
220 | + if (!Name##_empty(self)) {\ | |
221 | + self->begin = Name##_next(self, self->begin);\ | |
222 | + }\ | |
223 | + return elem;\ | |
224 | +}\ | |
225 | +\ | |
226 | +Type Name##_pop_back(Name *self)\ | |
227 | +{\ | |
228 | + assert(self && "Deque_pop_back");\ | |
229 | + assert(self->magic == self && "Deque_pop_back");\ | |
230 | + assert(!Name##_empty(self) && "Deque_pop_back");\ | |
231 | + if (!Name##_empty(self)) {\ | |
232 | + self->end = Name##_prev(self, self->end);\ | |
233 | + }\ | |
234 | + return self->buf[self->end];\ | |
235 | +}\ | |
236 | +\ | |
237 | +size_t Name##_size(Name *self)\ | |
238 | +{\ | |
239 | + assert(self && "Deque_size");\ | |
240 | + assert(self->magic == self && "Deque_size");\ | |
241 | + return Name##_distance(self, self->begin, self->end);\ | |
242 | +}\ | |
243 | +\ | |
244 | +size_t Name##_max_size(Name *self)\ | |
245 | +{\ | |
246 | + assert(self && "Deque_max_size");\ | |
247 | + assert(self->magic == self && "Deque_max_size");\ | |
248 | + return (self->nelems - 1);\ | |
249 | +}\ | |
250 | +\ | |
251 | +int Name##_empty(Name *self)\ | |
252 | +{\ | |
253 | + assert(self && "Deque_empty");\ | |
254 | + assert(self->magic == self && "Deque_empty");\ | |
255 | + return (self->begin == self->end);\ | |
256 | +}\ | |
257 | +\ | |
258 | +int Name##_full(Name *self)\ | |
259 | +{\ | |
260 | + assert(self && "Deque_full");\ | |
261 | + assert(self->magic == self && "Deque_full");\ | |
262 | + return (Name##_next(self, self->end) == self->begin);\ | |
263 | +}\ | |
264 | +\ | |
265 | +void Name##_clear(Name *self)\ | |
266 | +{\ | |
267 | + assert(self && "Deque_clear");\ | |
268 | + assert(self->magic == self && "Deque_clear");\ | |
269 | + self->end = self->begin;\ | |
270 | +}\ | |
271 | +\ | |
272 | +Type *Name##_at(Name *self, size_t idx)\ | |
273 | +{\ | |
274 | + assert(self && "Deque_at");\ | |
275 | + assert(self->magic == self && "Deque_at");\ | |
276 | + assert(Name##_size(self) > idx && "Deque_at");\ | |
277 | + return &self->buf[Name##_forward(self, self->begin, idx)];\ | |
278 | +}\ | |
279 | +\ | |
280 | +Type Name##_front(Name *self)\ | |
281 | +{\ | |
282 | + assert(self && "Deque_front");\ | |
283 | + assert(self->magic == self && "Deque_front");\ | |
284 | + assert(!Name##_empty(self) && "Deque_front");\ | |
285 | + return self->buf[self->begin];\ | |
286 | +}\ | |
287 | +\ | |
288 | +Type Name##_back(Name *self)\ | |
289 | +{\ | |
290 | + assert(self && "Deque_back");\ | |
291 | + assert(self->magic == self && "Deque_back");\ | |
292 | + assert(!Name##_empty(self) && "Deque_back");\ | |
293 | + return self->buf[Name##_prev(self, self->end)];\ | |
294 | +}\ | |
295 | +\ | |
296 | +static void Name##_move_forward(Name *self, size_t first, size_t last, size_t n)\ | |
297 | +{\ | |
298 | + size_t i;\ | |
299 | + for (i = Name##_prev(self, last); i != Name##_prev(self, first); i = Name##_prev(self, i)) {\ | |
300 | + self->buf[Name##_forward(self, i, n)] = self->buf[i];\ | |
301 | + }\ | |
302 | +}\ | |
303 | +\ | |
304 | +static void Name##_move_backward(Name *self, size_t first, size_t last, size_t n)\ | |
305 | +{\ | |
306 | + size_t i;\ | |
307 | + for (i = first; i != last; i = Name##_next(self, i)) {\ | |
308 | + self->buf[Name##_backward(self, i, n)] = self->buf[i];\ | |
309 | + }\ | |
310 | +}\ | |
311 | +\ | |
312 | +int Name##_insert(Name *self, size_t idx, Type elem)\ | |
313 | +{\ | |
314 | + assert(self && "Deque_insert");\ | |
315 | + assert(self->magic == self && "Deque_insert");\ | |
316 | + assert(Name##_size(self) >= idx && "Deque_insert");\ | |
317 | + return Name##_insert_n(self, idx, &elem, 1);\ | |
318 | +}\ | |
319 | +\ | |
320 | +int Name##_insert_n(Name *self, size_t idx, Type *elems, size_t n)\ | |
321 | +{\ | |
322 | + size_t i, j;\ | |
323 | + size_t pos;\ | |
324 | + assert(self && "Deque_insert_n");\ | |
325 | + assert(self->magic == self && "Deque_insert_n");\ | |
326 | + assert(Name##_size(self) >= idx && "Deque_insert_n");\ | |
327 | + assert(elems && "Deque_insert_n");\ | |
328 | + if (Name##_size(self) + n > Name##_max_size(self)) return 0;\ | |
329 | + pos = Name##_forward(self, self->begin, idx);\ | |
330 | + if (Name##_size(self) / 2 < idx) {\ | |
331 | + /* end側を移動 */\ | |
332 | + Name##_move_forward(self, pos, self->end, n);\ | |
333 | + self->end = Name##_forward(self, self->end, n);\ | |
334 | + } else {\ | |
335 | + /* begin側を移動 */\ | |
336 | + Name##_move_backward(self, self->begin, pos, n);\ | |
337 | + self->begin = Name##_backward(self, self->begin, n);\ | |
338 | + pos = Name##_backward(self, pos, n);\ | |
339 | + }\ | |
340 | + for (i = pos, j = 0; j < n; i = Name##_next(self, i), j++) {\ | |
341 | + self->buf[i] = elems[j];\ | |
342 | + }\ | |
343 | + return 1;\ | |
344 | +}\ | |
345 | +\ | |
346 | +void Name##_erase(Name *self, size_t idx)\ | |
347 | +{\ | |
348 | + assert(self && "Deque_erase");\ | |
349 | + assert(self->magic == self && "Deque_erase");\ | |
350 | + assert(Name##_size(self) >= idx + 1 && "Deque_erase");\ | |
351 | + Name##_erase_n(self, idx, 1);\ | |
352 | +}\ | |
353 | +\ | |
354 | +void Name##_erase_n(Name *self, size_t idx, size_t n)\ | |
355 | +{\ | |
356 | + size_t pos1;\ | |
357 | + size_t pos2;\ | |
358 | + assert(self && "Deque_erase_n");\ | |
359 | + assert(self->magic == self && "Deque_erase_n");\ | |
360 | + assert(Name##_size(self) >= idx + n && "Deque_erase_n");\ | |
361 | + pos1 = Name##_forward(self, self->begin, idx);\ | |
362 | + pos2 = Name##_forward(self, pos1, n);\ | |
363 | + if (Name##_distance(self, self->begin, pos1) >= \ | |
364 | + Name##_distance(self, pos2, self->end)) {\ | |
365 | + /* end側を移動 */\ | |
366 | + Name##_move_backward(self, pos2, self->end, n);\ | |
367 | + self->end = Name##_backward(self, self->end, n);\ | |
368 | + } else {\ | |
369 | + /* begin側を移動 */\ | |
370 | + Name##_move_forward(self, self->begin, pos1, n);\ | |
371 | + self->begin = Name##_forward(self, self->begin, n);\ | |
372 | + }\ | |
373 | +}\ | |
374 | +\ | |
375 | +int Name##_resize(Name *self, size_t n, Type elem)\ | |
376 | +{\ | |
377 | + size_t size;\ | |
378 | + assert(self && "Deque_resize");\ | |
379 | + assert(self->magic == self && "Deque_resize");\ | |
380 | + size = Name##_size(self);\ | |
381 | + if (size >= n) {\ | |
382 | + self->end = Name##_backward(self, self->end, size - n);\ | |
383 | + } else {\ | |
384 | + size_t i;\ | |
385 | + if (Name##_max_size(self) < n) {\ | |
386 | + return 0;\ | |
387 | + }\ | |
388 | + for (i = 0; i < n - size; i++) {\ | |
389 | + Name##_push_back(self, elem);\ | |
390 | + }\ | |
391 | + }\ | |
392 | + return 1;\ | |
393 | +}\ | |
394 | +\ | |
395 | + | |
396 | +#endif /* CSTL_DEQUE_H_INCLUDED */ |
@@ -0,0 +1,952 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2006, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file rbtree.h | |
27 | + * \brief 赤黒木 | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2006-10-29 | |
30 | + * | |
31 | + * このファイルを直接インクルードしないこと | |
32 | + */ | |
33 | +#ifndef CSTL_RBTREE_H_INCLUDED | |
34 | +#define CSTL_RBTREE_H_INCLUDED | |
35 | + | |
36 | +#include <stddef.h> | |
37 | +#include <stdlib.h> | |
38 | +#include <assert.h> | |
39 | + | |
40 | +#ifndef NDEBUG | |
41 | +#define RBTREE_MAGIC(x) x | |
42 | +#else | |
43 | +#define RBTREE_MAGIC(x) | |
44 | +#endif | |
45 | + | |
46 | +/*! | |
47 | + * \brief 赤黒木の色 | |
48 | + */ | |
49 | +typedef enum RBTreeColor_t { | |
50 | + RBTREE_RED, | |
51 | + RBTREE_BLACK, | |
52 | + RBTREE_HEAD | |
53 | +} RBTreeColor; | |
54 | + | |
55 | +/*! | |
56 | + * \brief ソートの順序 | |
57 | + */ | |
58 | +enum { | |
59 | + ASC = 0, | |
60 | + DESC | |
61 | +}; | |
62 | + | |
63 | +/*! | |
64 | + * \brief 単純比較ルーチン | |
65 | + */ | |
66 | +#define SIMPLE_CMP(x, y) ((x) - (y) == 0 ? 0 : (x) - (y) > 0 ? 1 : -1) | |
67 | + | |
68 | + | |
69 | +#define RBTREE_IMPLEMENT(Name, KeyType, ValueType, Compare, Order) \ | |
70 | +\ | |
71 | +typedef struct Name##Node_t Name##Node;\ | |
72 | +typedef struct Name##Node_t *Name##Iterator;\ | |
73 | +static Name##Node Name##_nil = {&Name##_nil, &Name##_nil, &Name##_nil, RBTREE_BLACK};\ | |
74 | +\ | |
75 | +static int Name##_cmp(KeyType x, KeyType y, int order)\ | |
76 | +{\ | |
77 | + return order ? Compare(y, x) : Compare(x, y);\ | |
78 | +}\ | |
79 | +\ | |
80 | +\ | |
81 | +static Name *Name##_new(void);\ | |
82 | +static void Name##_delete(Name *self);\ | |
83 | +static void Name##_clear(Name *self);\ | |
84 | +static int Name##_empty(Name *self);\ | |
85 | +static Name##Iterator Name##_insert(Name *self, KeyType key, ValueType value);\ | |
86 | +static void Name##_erase(Name *self, Name##Iterator pos);\ | |
87 | +static size_t Name##_count(Name *self, KeyType key);\ | |
88 | +static Name##Iterator Name##_find(Name *self, KeyType key);\ | |
89 | +static Name##Iterator Name##_lower_bound(Name *self, KeyType key);\ | |
90 | +static Name##Iterator Name##_upper_bound(Name *self, KeyType key);\ | |
91 | +static Name##Iterator Name##_begin(Name *self);\ | |
92 | +static Name##Iterator Name##_end(Name *self);\ | |
93 | +static Name##Iterator Name##_rbegin(Name *self);\ | |
94 | +static Name##Iterator Name##_rend(Name *self);\ | |
95 | +static Name##Iterator Name##_next(Name##Iterator pos);\ | |
96 | +static Name##Iterator Name##_prev(Name##Iterator pos);\ | |
97 | +\ | |
98 | +static Name##Node *Name##Node_new(KeyType key, ValueType value, RBTreeColor color);\ | |
99 | +static int Name##Node_is_head(Name##Node *self);\ | |
100 | +static int Name##Node_is_root(Name##Node *self);\ | |
101 | +static int Name##Node_is_nil(Name##Node *self);\ | |
102 | +static void Name##Node_set_left(Name##Node *self, Name##Node *t);\ | |
103 | +static void Name##Node_set_right(Name##Node *self, Name##Node *t);\ | |
104 | +static Name##Node *Name##_get_root(Name *self);\ | |
105 | +static void Name##_set_root(Name *self, Name##Node *t);\ | |
106 | +static Name##Node *Name##Node_find(Name *self, Name##Node *t, KeyType key);\ | |
107 | +static Name##Node *Name##Node_replace_subtree(Name##Node *self, Name##Node *t);\ | |
108 | +static void Name##Node_swap_parent_child(Name##Node *p, Name##Node *c);\ | |
109 | +static void Name##Node_swap(Name##Node *s, Name##Node *t);\ | |
110 | +static void Name##Node_rotate_right(Name##Node *self);\ | |
111 | +static void Name##Node_rotate_left(Name##Node *self);\ | |
112 | +static Name##Node *Name##Node_get_sibling(Name##Node *self);\ | |
113 | +static Name##Node *Name##Node_get_uncle(Name##Node *self);\ | |
114 | +static void Name##Node_balance_for_insert(Name##Node *n);\ | |
115 | +static void Name##Node_balance_for_erase(Name##Node *n, Name##Node *p_of_n);\ | |
116 | +\ | |
117 | +\ | |
118 | +static int Name##Node_is_head(Name##Node *self)\ | |
119 | +{\ | |
120 | + assert(self && "RBTreeNode_is_head");\ | |
121 | + return (self->color == RBTREE_HEAD);\ | |
122 | +}\ | |
123 | +\ | |
124 | +static int Name##Node_is_root(Name##Node *self)\ | |
125 | +{\ | |
126 | + assert(self && "RBTreeNode_is_root");\ | |
127 | + return Name##Node_is_head(self->parent);\ | |
128 | +}\ | |
129 | +\ | |
130 | +static int Name##Node_is_nil(Name##Node *self)\ | |
131 | +{\ | |
132 | + assert(self && "RBTreeNode_is_nil");\ | |
133 | + return (self == &Name##_nil);\ | |
134 | +}\ | |
135 | +\ | |
136 | +static void Name##Node_set_left(Name##Node *self, Name##Node *t)\ | |
137 | +{\ | |
138 | + assert(self && "RBTreeNode_set_left");\ | |
139 | + self->left = t;\ | |
140 | + if (!Name##Node_is_nil(t)) {\ | |
141 | + t->parent = self;\ | |
142 | + }\ | |
143 | +}\ | |
144 | +\ | |
145 | +static void Name##Node_set_right(Name##Node *self, Name##Node *t)\ | |
146 | +{\ | |
147 | + assert(self && "RBTreeNode_set_right");\ | |
148 | + self->right = t;\ | |
149 | + if (!Name##Node_is_nil(t)) {\ | |
150 | + t->parent = self;\ | |
151 | + }\ | |
152 | +}\ | |
153 | +\ | |
154 | +static Name##Node *Name##_get_root(Name *self)\ | |
155 | +{\ | |
156 | + assert(Name##Node_is_head(self) && "RBTree_get_root");\ | |
157 | + return self->right;\ | |
158 | +}\ | |
159 | +\ | |
160 | +static void Name##_set_root(Name *self, Name##Node *t)\ | |
161 | +{\ | |
162 | + assert(Name##Node_is_head(self) && "RBTree_set_root");\ | |
163 | + self->right = t;\ | |
164 | + if (!Name##Node_is_nil(t)) {\ | |
165 | + t->parent = self;\ | |
166 | + }\ | |
167 | +}\ | |
168 | +\ | |
169 | +static Name *Name##_new(void)\ | |
170 | +{\ | |
171 | + Name *self;\ | |
172 | + self = (Name *) malloc(sizeof(Name));\ | |
173 | + if (!self) return 0;\ | |
174 | + self->left = &Name##_nil;\ | |
175 | + self->right = &Name##_nil;\ | |
176 | + self->parent = &Name##_nil;\ | |
177 | + self->color = RBTREE_HEAD;\ | |
178 | + return self;\ | |
179 | +}\ | |
180 | +\ | |
181 | +static void Name##_clear(Name *self)\ | |
182 | +{\ | |
183 | + Name##Node *t;\ | |
184 | + Name##Node *tmp;\ | |
185 | + assert(Name##Node_is_head(self) && "RBTree_clear");\ | |
186 | + t = Name##_get_root(self);\ | |
187 | + if (Name##Node_is_nil(t)) return;\ | |
188 | + while (1) {\ | |
189 | + if (!Name##Node_is_nil(t->left)) {\ | |
190 | + t = t->left;\ | |
191 | + continue;\ | |
192 | + }\ | |
193 | + if (!Name##Node_is_nil(t->right)) {\ | |
194 | + t = t->right;\ | |
195 | + continue;\ | |
196 | + }\ | |
197 | + if (t == t->parent->left) {\ | |
198 | + t->parent->left = &Name##_nil;\ | |
199 | + } else {\ | |
200 | + t->parent->right = &Name##_nil;\ | |
201 | + }\ | |
202 | + tmp = t->parent;\ | |
203 | + free(t);\ | |
204 | + t = tmp;\ | |
205 | + if (Name##Node_is_head(t)) break;\ | |
206 | + }\ | |
207 | +}\ | |
208 | +\ | |
209 | +static void Name##_delete(Name *self)\ | |
210 | +{\ | |
211 | + assert(Name##Node_is_head(self) && "RBTree_delete");\ | |
212 | + Name##_clear(self);\ | |
213 | + free(self);\ | |
214 | +}\ | |
215 | +\ | |
216 | +static int Name##_empty(Name *self)\ | |
217 | +{\ | |
218 | + assert(Name##Node_is_head(self) && "RBTree_empty");\ | |
219 | + return Name##Node_is_nil(Name##_get_root(self));\ | |
220 | +}\ | |
221 | +\ | |
222 | +static Name##Node *Name##Node_find(Name *self, Name##Node *t, KeyType key)\ | |
223 | +{\ | |
224 | + int cmp;\ | |
225 | + while (!Name##Node_is_nil(t)) {\ | |
226 | + cmp = Name##_cmp(key, t->key, Order);\ | |
227 | + if (cmp < 0) {\ | |
228 | + t = t->left;\ | |
229 | + } else if (cmp > 0) {\ | |
230 | + t = t->right;\ | |
231 | + } else {\ | |
232 | + break;\ | |
233 | + }\ | |
234 | + }\ | |
235 | + return t;\ | |
236 | +}\ | |
237 | +\ | |
238 | +static Name##Iterator Name##_find(Name *self, KeyType key)\ | |
239 | +{\ | |
240 | + Name##Node *t;\ | |
241 | + assert(Name##Node_is_head(self) && "RBTree_find");\ | |
242 | + t = Name##Node_find(self, Name##_get_root(self), key);\ | |
243 | + return Name##Node_is_nil(t) ? Name##_end(self) : t;\ | |
244 | +}\ | |
245 | +\ | |
246 | +static size_t Name##_count(Name *self, KeyType key)\ | |
247 | +{\ | |
248 | + Name##Iterator first;\ | |
249 | + Name##Iterator last;\ | |
250 | + Name##Iterator pos;\ | |
251 | + size_t count = 0;\ | |
252 | + assert(Name##Node_is_head(self) && "RBTree_count");\ | |
253 | + first = Name##_lower_bound(self, key);\ | |
254 | + last = Name##_upper_bound(self, key);\ | |
255 | + for (pos = first; pos != last; pos = Name##_next(pos)) {\ | |
256 | + count++;\ | |
257 | + }\ | |
258 | + return count;\ | |
259 | +}\ | |
260 | +\ | |
261 | +static Name##Iterator Name##_lower_bound(Name *self, KeyType key)\ | |
262 | +{\ | |
263 | + Name##Node *t;\ | |
264 | + Name##Node *tmp;\ | |
265 | + assert(Name##Node_is_head(self) && "RBTree_lower_bound");\ | |
266 | + tmp = Name##_end(self);\ | |
267 | + t = Name##_get_root(self);\ | |
268 | + while (!Name##Node_is_nil(t)) {\ | |
269 | + if (Name##_cmp(key, t->key, Order) <= 0) {\ | |
270 | + tmp = t;\ | |
271 | + t = t->left;\ | |
272 | + } else {\ | |
273 | + t = t->right;\ | |
274 | + }\ | |
275 | + }\ | |
276 | + return tmp;\ | |
277 | +}\ | |
278 | +\ | |
279 | +static Name##Iterator Name##_upper_bound(Name *self, KeyType key)\ | |
280 | +{\ | |
281 | + Name##Node *t;\ | |
282 | + Name##Node *tmp;\ | |
283 | + assert(Name##Node_is_head(self) && "RBTree_upper_bound");\ | |
284 | + tmp = Name##_end(self);\ | |
285 | + t = Name##_get_root(self);\ | |
286 | + while (!Name##Node_is_nil(t)) {\ | |
287 | + if (Name##_cmp(key, t->key, Order) < 0) {\ | |
288 | + tmp = t;\ | |
289 | + t = t->left;\ | |
290 | + } else {\ | |
291 | + t = t->right;\ | |
292 | + }\ | |
293 | + }\ | |
294 | + return tmp;\ | |
295 | +}\ | |
296 | +\ | |
297 | +static Name##Node *Name##Node_replace_subtree(Name##Node *self, Name##Node *t)\ | |
298 | +{\ | |
299 | + assert(!Name##Node_is_head(self) && "RBTreeNode_replace_subtree");\ | |
300 | + assert(!Name##Node_is_head(t) && "RBTreeNode_replace_subtree");\ | |
301 | + if (self->parent->left == self) {\ | |
302 | + Name##Node_set_left(self->parent, t);\ | |
303 | + } else {\ | |
304 | + Name##Node_set_right(self->parent, t);\ | |
305 | + }\ | |
306 | + return self;\ | |
307 | +}\ | |
308 | +\ | |
309 | +static void Name##Node_swap_parent_child(Name##Node *p, Name##Node *c)\ | |
310 | +{\ | |
311 | + Name##Node *cl;\ | |
312 | + Name##Node *cr;\ | |
313 | + if (p->parent->left == p) {\ | |
314 | + Name##Node_set_left(p->parent, c);\ | |
315 | + } else {\ | |
316 | + Name##Node_set_right(p->parent, c);\ | |
317 | + }\ | |
318 | + cl = c->left;\ | |
319 | + cr = c->right;\ | |
320 | + if (p->left == c) {\ | |
321 | + Name##Node_set_left(c, p);\ | |
322 | + Name##Node_set_right(c, p->right);\ | |
323 | + } else {\ | |
324 | + Name##Node_set_right(c, p);\ | |
325 | + Name##Node_set_left(c, p->left);\ | |
326 | + }\ | |
327 | + Name##Node_set_left(p, cl);\ | |
328 | + Name##Node_set_right(p, cr);\ | |
329 | +}\ | |
330 | +\ | |
331 | +static void Name##Node_swap(Name##Node *s, Name##Node *t)\ | |
332 | +{\ | |
333 | + Name##Node *tp;\ | |
334 | + Name##Node *tl;\ | |
335 | + Name##Node *tr;\ | |
336 | + RBTreeColor c;\ | |
337 | + assert(!Name##Node_is_head(s) && "RBTreeNode_swap");\ | |
338 | + assert(!Name##Node_is_head(t) && "RBTreeNode_swap");\ | |
339 | + assert(!Name##Node_is_nil(s) && "RBTreeNode_swap");\ | |
340 | + assert(!Name##Node_is_nil(t) && "RBTreeNode_swap");\ | |
341 | + if (t->parent == s) {\ | |
342 | + Name##Node_swap_parent_child(s, t);\ | |
343 | + } else if (s->parent == t) {\ | |
344 | + Name##Node_swap_parent_child(t, s);\ | |
345 | + } else {\ | |
346 | + tp = t->parent;\ | |
347 | + tl = t->left;\ | |
348 | + tr = t->right;\ | |
349 | + if (s->parent->left == s) {\ | |
350 | + Name##Node_set_left(s->parent, t);\ | |
351 | + } else {\ | |
352 | + Name##Node_set_right(s->parent, t);\ | |
353 | + }\ | |
354 | + Name##Node_set_left(t, s->left);\ | |
355 | + Name##Node_set_right(t, s->right);\ | |
356 | + if (tp->left == t) {\ | |
357 | + Name##Node_set_left(tp, s);\ | |
358 | + } else {\ | |
359 | + Name##Node_set_right(tp, s);\ | |
360 | + }\ | |
361 | + Name##Node_set_left(s, tl);\ | |
362 | + Name##Node_set_right(s, tr);\ | |
363 | + }\ | |
364 | + c = s->color;\ | |
365 | + s->color = t->color;\ | |
366 | + t->color = c;\ | |
367 | +}\ | |
368 | +\ | |
369 | +static void Name##Node_rotate_right(Name##Node *self)\ | |
370 | +{\ | |
371 | + Name##Node *p;\ | |
372 | + Name##Node *n;\ | |
373 | + assert(!Name##Node_is_head(self) && "RBTreeNode_rotate_right");\ | |
374 | + assert(!Name##Node_is_nil(self) && "RBTreeNode_rotate_right");\ | |
375 | + p = self->parent;\ | |
376 | + n = self->left;\ | |
377 | + assert(!Name##Node_is_nil(n) && "RBTreeNode_rotate_right");\ | |
378 | + Name##Node_set_left(self, n->right);\ | |
379 | + Name##Node_set_right(n, self);\ | |
380 | + if (p->left == self) {\ | |
381 | + Name##Node_set_left(p, n);\ | |
382 | + } else {\ | |
383 | + Name##Node_set_right(p, n);\ | |
384 | + }\ | |
385 | +}\ | |
386 | +\ | |
387 | +static void Name##Node_rotate_left(Name##Node *self)\ | |
388 | +{\ | |
389 | + Name##Node *p;\ | |
390 | + Name##Node *n;\ | |
391 | + assert(!Name##Node_is_head(self) && "RBTreeNode_rotate_left");\ | |
392 | + assert(!Name##Node_is_nil(self) && "RBTreeNode_rotate_left");\ | |
393 | + p = self->parent;\ | |
394 | + n = self->right;\ | |
395 | + assert(!Name##Node_is_nil(n) && "RBTreeNode_rotate_left");\ | |
396 | + Name##Node_set_right(self, n->left);\ | |
397 | + Name##Node_set_left(n, self);\ | |
398 | + if (p->left == self) {\ | |
399 | + Name##Node_set_left(p, n);\ | |
400 | + } else {\ | |
401 | + Name##Node_set_right(p, n);\ | |
402 | + }\ | |
403 | +}\ | |
404 | +\ | |
405 | +static Name##Node *Name##Node_get_sibling(Name##Node *self)\ | |
406 | +{\ | |
407 | + assert(!Name##Node_is_head(self) && "RBTreeNode_get_sibling");\ | |
408 | + assert(!Name##Node_is_nil(self) && "RBTreeNode_get_sibling");\ | |
409 | + assert(!Name##Node_is_root(self) && "RBTreeNode_get_sibling");\ | |
410 | + return (self->parent->left == self) ? \ | |
411 | + self->parent->right : self->parent->left;\ | |
412 | +}\ | |
413 | +\ | |
414 | +static Name##Node *Name##Node_get_uncle(Name##Node *self)\ | |
415 | +{\ | |
416 | + Name##Node *g;\ | |
417 | + assert(!Name##Node_is_head(self) && "RBTreeNode_get_uncle");\ | |
418 | + assert(!Name##Node_is_nil(self) && "RBTreeNode_get_uncle");\ | |
419 | + assert(!Name##Node_is_root(self) && "RBTreeNode_get_uncle");\ | |
420 | + assert(!Name##Node_is_root(self->parent) && "RBTreeNode_get_uncle");\ | |
421 | + g = self->parent->parent;\ | |
422 | + assert(!Name##Node_is_nil(g) && "RBTreeNode_get_uncle");\ | |
423 | + assert(!Name##Node_is_head(g) && "RBTreeNode_get_uncle");\ | |
424 | + return (g->left == self->parent) ?\ | |
425 | + g->right : g->left;\ | |
426 | +}\ | |
427 | +\ | |
428 | +static void Name##Node_balance_for_insert(Name##Node *n)\ | |
429 | +{\ | |
430 | + Name##Node *p;\ | |
431 | + Name##Node *g;\ | |
432 | + Name##Node *u;\ | |
433 | + Name##Node *tmp;\ | |
434 | + while (1) {\ | |
435 | + p = n->parent;\ | |
436 | + if (Name##Node_is_root(n)) {\ | |
437 | + /* case 1 nがroot */\ | |
438 | + n->color = RBTREE_BLACK;\ | |
439 | + break;\ | |
440 | + }\ | |
441 | + if (p->color == RBTREE_BLACK) {\ | |
442 | + /* case 2 pが黒 */\ | |
443 | + break;\ | |
444 | + }\ | |
445 | + /* 以下、pは赤、gは黒 */\ | |
446 | + g = p->parent;\ | |
447 | + u = Name##Node_get_uncle(n);\ | |
448 | + if (u->color == RBTREE_RED) {\ | |
449 | + /* case 3 uが赤 */\ | |
450 | + g->color = RBTREE_RED;\ | |
451 | + p->color = RBTREE_BLACK;\ | |
452 | + u->color = RBTREE_BLACK;\ | |
453 | + n = g;\ | |
454 | + /* gをnにして再調整。最悪の場合、根まで伝播 */\ | |
455 | + continue;\ | |
456 | + }\ | |
457 | + /* 以下、uは黒 */\ | |
458 | + if (g->left == p && p->right == n) {\ | |
459 | + /* case 4 pがgのleft */\ | |
460 | + Name##Node_rotate_left(p);\ | |
461 | + tmp = p;\ | |
462 | + p = n;\ | |
463 | + n = tmp;\ | |
464 | + /* case 5 leftへ */\ | |
465 | + } else if (g->right == p && p->left == n) {\ | |
466 | + /* case 4 pがgのright */\ | |
467 | + Name##Node_rotate_right(p);\ | |
468 | + tmp = p;\ | |
469 | + p = n;\ | |
470 | + n = tmp;\ | |
471 | + /* case 5 rightへ */\ | |
472 | + }\ | |
473 | + if (g->left == p) {\ | |
474 | + /* case 5 left */\ | |
475 | + Name##Node_rotate_right(g);\ | |
476 | + } else if (g->right == p) {\ | |
477 | + /* case 5 right */\ | |
478 | + Name##Node_rotate_left(g);\ | |
479 | + } else {\ | |
480 | + assert(0 && "RBTreeNode_balance_for_insert");\ | |
481 | + }\ | |
482 | + p->color = RBTREE_BLACK;\ | |
483 | + g->color = RBTREE_RED;\ | |
484 | + break;\ | |
485 | + }\ | |
486 | +}\ | |
487 | +\ | |
488 | +static Name##Iterator Name##_insert(Name *self, KeyType key, ValueType value)\ | |
489 | +{\ | |
490 | + Name##Node *n;\ | |
491 | + Name##Node *tmp;\ | |
492 | + assert(Name##Node_is_head(self) && "RBTree_insert");\ | |
493 | + n = Name##_get_root(self);\ | |
494 | + if (Name##Node_is_nil(n)) {\ | |
495 | + /* rootになる */\ | |
496 | + Name##Node *root = Name##Node_new(key, value, RBTREE_BLACK);\ | |
497 | + if (!root) return 0; /* メモリ不足 */\ | |
498 | + Name##_set_root(self, root);\ | |
499 | + return root;\ | |
500 | + }\ | |
501 | + /* 2分探索木の挿入 */\ | |
502 | + while (!Name##Node_is_nil(n)) {\ | |
503 | + tmp = n;\ | |
504 | + if (Name##_cmp(key, n->key, Order) < 0) {\ | |
505 | + n = n->left;\ | |
506 | + } else {\ | |
507 | + /* 同じ値なら右へ */\ | |
508 | + n = n->right;\ | |
509 | + }\ | |
510 | + }\ | |
511 | + n = Name##Node_new(key, value, RBTREE_RED);\ | |
512 | + if (!n) return 0; /* メモリ不足 */\ | |
513 | + if (Name##_cmp(key, tmp->key, Order) < 0) {\ | |
514 | + Name##Node_set_left(tmp, n);\ | |
515 | + } else {\ | |
516 | + Name##Node_set_right(tmp, n);\ | |
517 | + }\ | |
518 | + Name##Node_balance_for_insert(n);\ | |
519 | + return n;\ | |
520 | +}\ | |
521 | +\ | |
522 | +static void Name##Node_balance_for_erase(Name##Node *n, Name##Node *p_of_n)\ | |
523 | +{\ | |
524 | + Name##Node *p;\ | |
525 | + Name##Node *s;\ | |
526 | + Name##Node *sl;\ | |
527 | + Name##Node *sr;\ | |
528 | + RBTreeColor c;\ | |
529 | + if (n->color == RBTREE_RED) {\ | |
530 | + /* case 0 nが赤 */\ | |
531 | + n->color = RBTREE_BLACK;\ | |
532 | + return;\ | |
533 | + }\ | |
534 | + while (1) {\ | |
535 | + if (Name##Node_is_root(n)) {\ | |
536 | + /* case 1 nがroot */\ | |
537 | + n->color = RBTREE_BLACK;\ | |
538 | + break;\ | |
539 | + }\ | |
540 | + if (Name##Node_is_nil(n)) {\ | |
541 | + assert(!(Name##Node_is_nil(p_of_n->left) && Name##Node_is_nil(p_of_n->right)) && "RBTreeNode_balance_for_erase");\ | |
542 | + p = p_of_n;\ | |
543 | + s = (n == p_of_n->left) ? p_of_n->right : p_of_n->left;\ | |
544 | + } else {\ | |
545 | + p = n->parent;\ | |
546 | + s = Name##Node_get_sibling(n);\ | |
547 | + }\ | |
548 | + assert(!Name##Node_is_nil(s) && "RBTreeNode_balance_for_erase");\ | |
549 | + if (s->color == RBTREE_RED) {\ | |
550 | + /* case 2 sが赤 */\ | |
551 | + p->color = RBTREE_RED;\ | |
552 | + s->color = RBTREE_BLACK;\ | |
553 | + if (p->left == n) {\ | |
554 | + Name##Node_rotate_left(p);\ | |
555 | + s = p->right;\ | |
556 | + } else {\ | |
557 | + Name##Node_rotate_right(p);\ | |
558 | + s = p->left;\ | |
559 | + }\ | |
560 | + }\ | |
561 | + /* 以下、sは黒 */\ | |
562 | + assert(!Name##Node_is_nil(s) && "RBTreeNode_balance_for_erase");\ | |
563 | + sl = s->left;\ | |
564 | + sr = s->right;\ | |
565 | + if (p->color == RBTREE_BLACK && sl->color == RBTREE_BLACK && sr->color == RBTREE_BLACK) {\ | |
566 | + /* case 3 */\ | |
567 | + s->color = RBTREE_RED;\ | |
568 | + n = p;\ | |
569 | + /* pをnにして再調整。最悪の場合、根まで伝播 */\ | |
570 | + continue;\ | |
571 | + }\ | |
572 | + if (p->color == RBTREE_RED && sl->color == RBTREE_BLACK && sr->color == RBTREE_BLACK) {\ | |
573 | + /* case 4 */\ | |
574 | + p->color = RBTREE_BLACK;\ | |
575 | + s->color = RBTREE_RED;\ | |
576 | + break;\ | |
577 | + }\ | |
578 | + if (p->left == n && sl->color == RBTREE_RED && sr->color == RBTREE_BLACK) {\ | |
579 | + /* case 5 nがpのleft */\ | |
580 | + sl->color = RBTREE_BLACK;\ | |
581 | + s->color = RBTREE_RED;\ | |
582 | + Name##Node_rotate_right(s);\ | |
583 | + sr = s;\ | |
584 | + s = sl;\ | |
585 | + /* case 6 leftへ */\ | |
586 | + } else if (p->right == n && sl->color == RBTREE_BLACK && sr->color == RBTREE_RED) {\ | |
587 | + /* case 5 nがpのright */\ | |
588 | + sr->color = RBTREE_BLACK;\ | |
589 | + s->color = RBTREE_RED;\ | |
590 | + Name##Node_rotate_left(s);\ | |
591 | + sl = s;\ | |
592 | + s = sr;\ | |
593 | + /* case 6 rightへ */\ | |
594 | + }\ | |
595 | + if (p->left == n && sr->color == RBTREE_RED) {\ | |
596 | + /* case 6 left */\ | |
597 | + sr->color = RBTREE_BLACK;\ | |
598 | + Name##Node_rotate_left(p);\ | |
599 | + } else if (p->right == n && sl->color == RBTREE_RED) {\ | |
600 | + /* case 6 right */\ | |
601 | + sl->color = RBTREE_BLACK;\ | |
602 | + Name##Node_rotate_right(p);\ | |
603 | + } else {\ | |
604 | + assert(0 && "RBTreeNode_balance_for_erase");\ | |
605 | + }\ | |
606 | + c = p->color;\ | |
607 | + p->color = s->color;\ | |
608 | + s->color = c;\ | |
609 | + break;\ | |
610 | + }\ | |
611 | +}\ | |
612 | +\ | |
613 | +static void Name##_erase(Name *self, Name##Iterator pos)\ | |
614 | +{\ | |
615 | + Name##Node *n;\ | |
616 | + Name##Node *x;\ | |
617 | + assert(Name##Node_is_head(self) && "RBTree_erase");\ | |
618 | + assert(!Name##Node_is_head(pos) && "RBTree_erase");\ | |
619 | + n = pos;\ | |
620 | + assert(!Name##Node_is_nil(n) && "RBTree_erase");\ | |
621 | + if (Name##Node_is_nil(n->left) && Name##Node_is_nil(n->right)) {\ | |
622 | + if (Name##Node_is_root(n)) {\ | |
623 | + /* 最後の一つを削除 */\ | |
624 | + Name##_set_root(self, &Name##_nil);\ | |
625 | + } else {\ | |
626 | + n = Name##Node_replace_subtree(n, &Name##_nil);\ | |
627 | + if (n->color == RBTREE_BLACK) {\ | |
628 | + Name##Node_balance_for_erase(&Name##_nil, n->parent);\ | |
629 | + }\ | |
630 | + }\ | |
631 | + goto end;\ | |
632 | + }\ | |
633 | + if (Name##Node_is_nil(n->left)) {\ | |
634 | + n = Name##Node_replace_subtree(n, n->right);\ | |
635 | + if (n->color == RBTREE_BLACK) {\ | |
636 | + assert(!Name##Node_is_nil(n->right) && "RBTree_erase");\ | |
637 | + Name##Node_balance_for_erase(n->right, 0);\ | |
638 | + }\ | |
639 | + goto end;\ | |
640 | + }\ | |
641 | + if (Name##Node_is_nil(n->right)) {\ | |
642 | + n = Name##Node_replace_subtree(n, n->left);\ | |
643 | + if (n->color == RBTREE_BLACK) {\ | |
644 | + assert(!Name##Node_is_nil(n->left) && "RBTree_erase");\ | |
645 | + Name##Node_balance_for_erase(n->left, 0);\ | |
646 | + }\ | |
647 | + goto end;\ | |
648 | + }\ | |
649 | + assert(!(Name##Node_is_nil(n->left) || Name##Node_is_nil(n->right)) && "RBTree_erase");\ | |
650 | + x = n->left;\ | |
651 | + while (!Name##Node_is_nil(x->right)) {\ | |
652 | + x = x->right;\ | |
653 | + }\ | |
654 | + Name##Node_swap(n, x);\ | |
655 | + n = Name##Node_replace_subtree(n, n->left);\ | |
656 | + if (n->color == RBTREE_BLACK) {\ | |
657 | + assert(!Name##Node_is_nil(n) && "RBTree_erase");\ | |
658 | + Name##Node_balance_for_erase(n->left, n->parent);\ | |
659 | + }\ | |
660 | +end:\ | |
661 | + free(n);\ | |
662 | +}\ | |
663 | +\ | |
664 | +static Name##Iterator Name##_begin(Name *self)\ | |
665 | +{\ | |
666 | + Name##Node *t;\ | |
667 | + Name##Node *tmp;\ | |
668 | + assert(Name##Node_is_head(self) && "RBTree_begin");\ | |
669 | + tmp = Name##_end(self);\ | |
670 | + t = Name##_get_root(self);\ | |
671 | + while (!Name##Node_is_nil(t)) {\ | |
672 | + tmp = t;\ | |
673 | + t = t->left;\ | |
674 | + }\ | |
675 | + return tmp;\ | |
676 | +}\ | |
677 | +\ | |
678 | +static Name##Iterator Name##_end(Name *self)\ | |
679 | +{\ | |
680 | + assert(Name##Node_is_head(self) && "RBTree_end");\ | |
681 | + return self;\ | |
682 | +}\ | |
683 | +\ | |
684 | +static Name##Iterator Name##_rbegin(Name *self)\ | |
685 | +{\ | |
686 | + Name##Node *t;\ | |
687 | + Name##Node *tmp;\ | |
688 | + assert(Name##Node_is_head(self) && "RBTree_rbegin");\ | |
689 | + tmp = Name##_rend(self);\ | |
690 | + t = Name##_get_root(self);\ | |
691 | + while (!Name##Node_is_nil(t)) {\ | |
692 | + tmp = t;\ | |
693 | + t = t->right;\ | |
694 | + }\ | |
695 | + return tmp;\ | |
696 | +}\ | |
697 | +\ | |
698 | +static Name##Iterator Name##_rend(Name *self)\ | |
699 | +{\ | |
700 | + assert(Name##Node_is_head(self) && "RBTree_rend");\ | |
701 | + return self;\ | |
702 | +}\ | |
703 | +\ | |
704 | +static Name##Iterator Name##_next(Name##Iterator pos)\ | |
705 | +{\ | |
706 | + assert(!Name##Node_is_head(pos) && "RBTree_next");\ | |
707 | + assert(!Name##Node_is_nil(pos) && "RBTree_next");\ | |
708 | + /* 下位検索 */\ | |
709 | + if (!Name##Node_is_nil(pos->right)) {\ | |
710 | + pos = pos->right;\ | |
711 | + while (!Name##Node_is_nil(pos->left)) {\ | |
712 | + pos = pos->left;\ | |
713 | + }\ | |
714 | + return pos;\ | |
715 | + }\ | |
716 | + /* 上位検索 */\ | |
717 | + while (!Name##Node_is_root(pos) && pos == pos->parent->right) {\ | |
718 | + pos = pos->parent;\ | |
719 | + }\ | |
720 | + /* 引数のposがrbegin()の時、pos->parentはend()となる。 */\ | |
721 | + return pos->parent;\ | |
722 | +}\ | |
723 | +\ | |
724 | +static Name##Iterator Name##_prev(Name##Iterator pos)\ | |
725 | +{\ | |
726 | + assert(!Name##Node_is_head(pos) && "RBTree_prev");\ | |
727 | + assert(!Name##Node_is_nil(pos) && "RBTree_prev");\ | |
728 | + /* 下位検索 */\ | |
729 | + if (!Name##Node_is_nil(pos->left)) {\ | |
730 | + pos = pos->left;\ | |
731 | + while (!Name##Node_is_nil(pos->right)) {\ | |
732 | + pos = pos->right;\ | |
733 | + }\ | |
734 | + return pos;\ | |
735 | + }\ | |
736 | + /* 上位検索 */\ | |
737 | + while (!Name##Node_is_root(pos) && pos == pos->parent->left) {\ | |
738 | + pos = pos->parent;\ | |
739 | + }\ | |
740 | + /* 引数のposがbegin()の時、pos->parentはrend()となる。 */\ | |
741 | + return pos->parent;\ | |
742 | +}\ | |
743 | +\ | |
744 | + | |
745 | + | |
746 | + | |
747 | +#define RBTREE_WRAPPER_INTERFACE(Name, KeyType, ValueType) \ | |
748 | +\ | |
749 | +typedef struct Name##_t Name;\ | |
750 | +typedef struct Name##RBTreeNode_t *Name##Iterator;\ | |
751 | +\ | |
752 | +Name *Name##_new(void);\ | |
753 | +Name *Name##_new_copy(Name *x);\ | |
754 | +void Name##_delete(Name *self);\ | |
755 | +void Name##_clear(Name *self);\ | |
756 | +int Name##_empty(Name *self);\ | |
757 | +size_t Name##_size(Name *self);\ | |
758 | +Name##Iterator Name##_erase(Name *self, Name##Iterator pos);\ | |
759 | +Name##Iterator Name##_erase_range(Name *self, Name##Iterator first, Name##Iterator last);\ | |
760 | +size_t Name##_erase_key(Name *self, KeyType key);\ | |
761 | +size_t Name##_count(Name *self, KeyType key);\ | |
762 | +Name##Iterator Name##_find(Name *self, KeyType key);\ | |
763 | +Name##Iterator Name##_lower_bound(Name *self, KeyType key);\ | |
764 | +Name##Iterator Name##_upper_bound(Name *self, KeyType key);\ | |
765 | +Name##Iterator Name##_begin(Name *self);\ | |
766 | +Name##Iterator Name##_end(Name *self);\ | |
767 | +Name##Iterator Name##_rbegin(Name *self);\ | |
768 | +Name##Iterator Name##_rend(Name *self);\ | |
769 | +Name##Iterator Name##_next(Name##Iterator pos);\ | |
770 | +Name##Iterator Name##_prev(Name##Iterator pos);\ | |
771 | +KeyType Name##_key(Name##Iterator pos);\ | |
772 | + | |
773 | + | |
774 | +#define RBTREE_WRAPPER_IMPLEMENT(Name, KeyType, ValueType, Compare, Order) \ | |
775 | +\ | |
776 | +typedef struct Name##RBTreeNode_t Name##RBTree;\ | |
777 | +/*! | |
778 | + * \brief set/map構造体 | |
779 | + */\ | |
780 | +struct Name##_t {\ | |
781 | + Name##RBTree *tree;\ | |
782 | + size_t nelems;\ | |
783 | + RBTREE_MAGIC(void *magic;)\ | |
784 | +};\ | |
785 | +\ | |
786 | +RBTREE_IMPLEMENT(Name##RBTree, KeyType, ValueType, Compare, Order)\ | |
787 | +\ | |
788 | +Name *Name##_new(void)\ | |
789 | +{\ | |
790 | + Name *self;\ | |
791 | + self = (Name *) malloc(sizeof(Name));\ | |
792 | + if (!self) return 0;\ | |
793 | + self->tree = Name##RBTree_new();\ | |
794 | + if (!self->tree) {\ | |
795 | + free(self);\ | |
796 | + return 0;\ | |
797 | + }\ | |
798 | + self->nelems = 0;\ | |
799 | + RBTREE_MAGIC(self->magic = self);\ | |
800 | + return self;\ | |
801 | +}\ | |
802 | +\ | |
803 | +void Name##_delete(Name *self)\ | |
804 | +{\ | |
805 | + assert(self && "RBTree_delete");\ | |
806 | + assert(self->magic == self && "RBTree_delete");\ | |
807 | + Name##RBTree_delete(self->tree);\ | |
808 | + RBTREE_MAGIC(self->magic = 0);\ | |
809 | + free(self);\ | |
810 | +}\ | |
811 | +\ | |
812 | +void Name##_clear(Name *self)\ | |
813 | +{\ | |
814 | + assert(self && "RBTree_clear");\ | |
815 | + assert(self->magic == self && "RBTree_clear");\ | |
816 | + Name##RBTree_clear(self->tree);\ | |
817 | + self->nelems = 0;\ | |
818 | +}\ | |
819 | +\ | |
820 | +int Name##_empty(Name *self)\ | |
821 | +{\ | |
822 | + assert(self && "RBTree_empty");\ | |
823 | + assert(self->magic == self && "RBTree_empty");\ | |
824 | + return Name##RBTree_empty(self->tree);\ | |
825 | +}\ | |
826 | +\ | |
827 | +size_t Name##_size(Name *self)\ | |
828 | +{\ | |
829 | + assert(self && "RBTree_size");\ | |
830 | + assert(self->magic == self && "RBTree_size");\ | |
831 | + return self->nelems;\ | |
832 | +}\ | |
833 | +\ | |
834 | +Name##Iterator Name##_erase(Name *self, Name##Iterator pos)\ | |
835 | +{\ | |
836 | + Name##Iterator tmp;\ | |
837 | + assert(self && "RBTree_erase");\ | |
838 | + assert(self->magic == self && "RBTree_erase");\ | |
839 | + tmp = Name##_next(pos);\ | |
840 | + Name##RBTree_erase(self->tree, pos);\ | |
841 | + self->nelems--;\ | |
842 | + return tmp;\ | |
843 | +}\ | |
844 | +\ | |
845 | +Name##Iterator Name##_erase_range(Name *self, Name##Iterator first, Name##Iterator last)\ | |
846 | +{\ | |
847 | + Name##Iterator pos;\ | |
848 | + assert(self && "RBTree_erase_range");\ | |
849 | + assert(self->magic == self && "RBTree_erase_range");\ | |
850 | + assert(first && "RBTree_erase_range");\ | |
851 | + assert(last && "RBTree_erase_range");\ | |
852 | + pos = first;\ | |
853 | + while (pos != last) {\ | |
854 | + pos = Name##_erase(self, pos);\ | |
855 | + }\ | |
856 | + return pos;\ | |
857 | +}\ | |
858 | +\ | |
859 | +size_t Name##_erase_key(Name *self, KeyType key)\ | |
860 | +{\ | |
861 | + size_t count = 0;\ | |
862 | + Name##Iterator pos;\ | |
863 | + Name##Iterator last;\ | |
864 | + assert(self && "RBTree_erase_key");\ | |
865 | + assert(self->magic == self && "RBTree_erase_key");\ | |
866 | + pos = Name##_lower_bound(self, key);\ | |
867 | + last = Name##_upper_bound(self, key);\ | |
868 | + while (pos != last) {\ | |
869 | + pos = Name##_erase(self, pos);\ | |
870 | + count++;\ | |
871 | + }\ | |
872 | + return count;\ | |
873 | +}\ | |
874 | +\ | |
875 | +size_t Name##_count(Name *self, KeyType key)\ | |
876 | +{\ | |
877 | + assert(self && "RBTree_count");\ | |
878 | + assert(self->magic == self && "RBTree_count");\ | |
879 | + return Name##RBTree_count(self->tree, key);\ | |
880 | +}\ | |
881 | +\ | |
882 | +Name##Iterator Name##_find(Name *self, KeyType key)\ | |
883 | +{\ | |
884 | + assert(self && "RBTree_find");\ | |
885 | + assert(self->magic == self && "RBTree_find");\ | |
886 | + return Name##RBTree_find(self->tree, key);\ | |
887 | +}\ | |
888 | +\ | |
889 | +Name##Iterator Name##_lower_bound(Name *self, KeyType key)\ | |
890 | +{\ | |
891 | + assert(self && "RBTree_lower_bound");\ | |
892 | + assert(self->magic == self && "RBTree_lower_bound");\ | |
893 | + return Name##RBTree_lower_bound(self->tree, key);\ | |
894 | +}\ | |
895 | +\ | |
896 | +Name##Iterator Name##_upper_bound(Name *self, KeyType key)\ | |
897 | +{\ | |
898 | + assert(self && "RBTree_upper_bound");\ | |
899 | + assert(self->magic == self && "RBTree_upper_bound");\ | |
900 | + return Name##RBTree_upper_bound(self->tree, key);\ | |
901 | +}\ | |
902 | +\ | |
903 | +Name##Iterator Name##_begin(Name *self)\ | |
904 | +{\ | |
905 | + assert(self && "RBTree_begin");\ | |
906 | + assert(self->magic == self && "RBTree_begin");\ | |
907 | + return Name##RBTree_begin(self->tree);\ | |
908 | +}\ | |
909 | +\ | |
910 | +Name##Iterator Name##_end(Name *self)\ | |
911 | +{\ | |
912 | + assert(self && "RBTree_end");\ | |
913 | + assert(self->magic == self && "RBTree_end");\ | |
914 | + return Name##RBTree_end(self->tree);\ | |
915 | +}\ | |
916 | +\ | |
917 | +Name##Iterator Name##_rbegin(Name *self)\ | |
918 | +{\ | |
919 | + assert(self && "RBTree_rbegin");\ | |
920 | + assert(self->magic == self && "RBTree_rbegin");\ | |
921 | + return Name##RBTree_rbegin(self->tree);\ | |
922 | +}\ | |
923 | +\ | |
924 | +Name##Iterator Name##_rend(Name *self)\ | |
925 | +{\ | |
926 | + assert(self && "RBTree_rend");\ | |
927 | + assert(self->magic == self && "RBTree_rend");\ | |
928 | + return Name##RBTree_rend(self->tree);\ | |
929 | +}\ | |
930 | +\ | |
931 | +Name##Iterator Name##_next(Name##Iterator pos)\ | |
932 | +{\ | |
933 | + assert(pos && "RBTree_next");\ | |
934 | + return Name##RBTree_next(pos);\ | |
935 | +}\ | |
936 | +\ | |
937 | +Name##Iterator Name##_prev(Name##Iterator pos)\ | |
938 | +{\ | |
939 | + assert(pos && "RBTree_prev");\ | |
940 | + return Name##RBTree_prev(pos);\ | |
941 | +}\ | |
942 | +\ | |
943 | +KeyType Name##_key(Name##Iterator pos)\ | |
944 | +{\ | |
945 | + assert(pos && "RBTree_key");\ | |
946 | + assert(!Name##RBTreeNode_is_head(pos) && "RBTree_key");\ | |
947 | + return pos->key;\ | |
948 | +}\ | |
949 | +\ | |
950 | + | |
951 | + | |
952 | +#endif /* CSTL_RBTREE_H_INCLUDED */ |
@@ -0,0 +1,707 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2007, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file string.h | |
27 | + * \brief 文字列コンテナ | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2007-01-09 | |
30 | + */ | |
31 | +#ifndef CSTL_STRING_H_INCLUDED | |
32 | +#define CSTL_STRING_H_INCLUDED | |
33 | + | |
34 | +#include <stddef.h> | |
35 | +#include <stdlib.h> | |
36 | +#include <assert.h> | |
37 | +#include "vector.h" | |
38 | + | |
39 | +#ifdef __cplusplus | |
40 | +#define STRING_BEGIN_EXTERN_C() extern "C" { | |
41 | +#define STRING_END_EXTERN_C() } | |
42 | +#else | |
43 | +#define STRING_BEGIN_EXTERN_C() | |
44 | +#define STRING_END_EXTERN_C() | |
45 | +#endif | |
46 | + | |
47 | +#ifndef NDEBUG | |
48 | +#define STRING_MAGIC(x) x | |
49 | +#else | |
50 | +#define STRING_MAGIC(x) | |
51 | +#endif | |
52 | + | |
53 | +/*! | |
54 | + * \brief 検索失敗用インデックス | |
55 | + */ | |
56 | +#define NPOS ((size_t)-1) | |
57 | + | |
58 | +/*! | |
59 | + * \brief インターフェイスマクロ | |
60 | + * | |
61 | + * \param Name コンテナ名 | |
62 | + * \param Type 要素の型 | |
63 | + */ | |
64 | +#define STRING_INTERFACE(Name, Type) \ | |
65 | +typedef struct Name##_t Name;\ | |
66 | +\ | |
67 | +STRING_BEGIN_EXTERN_C()\ | |
68 | +Name *Name##_new(void);\ | |
69 | +Name *Name##_new_cstr(Type *cstr, size_t cstr_len);\ | |
70 | +Name *Name##_new_c(size_t n, Type c);\ | |
71 | +Name *Name##_new_copy(Name *x);\ | |
72 | +void Name##_delete(Name *self);\ | |
73 | +void Name##_clear(Name *self);\ | |
74 | +size_t Name##_size(Name *self);\ | |
75 | +size_t Name##_length(Name *self);\ | |
76 | +size_t Name##_capacity(Name *self);\ | |
77 | +int Name##_reserve(Name *self, size_t n);\ | |
78 | +void Name##_shrink(Name *self, size_t n);\ | |
79 | +int Name##_empty(Name *self);\ | |
80 | +int Name##_compare(Name *x, Name *y);\ | |
81 | +Type *Name##_at(Name *self, size_t idx);\ | |
82 | +Type *Name##_c_str(Name *self);\ | |
83 | +void Name##_erase(Name *self, size_t idx, size_t len);\ | |
84 | +int Name##_resize(Name *self, size_t n, Type c);\ | |
85 | +int Name##_assign(Name *self, Type *cstr, size_t cstr_len);\ | |
86 | +int Name##_assign_c(Name *self, size_t n, Type c);\ | |
87 | +int Name##_append(Name *self, Type *cstr, size_t cstr_len);\ | |
88 | +int Name##_append_c(Name *self, size_t n, Type c);\ | |
89 | +int Name##_push_back(Name *self, Type c);\ | |
90 | +int Name##_insert(Name *self, size_t idx, Type *cstr, size_t cstr_len);\ | |
91 | +int Name##_insert_c(Name *self, size_t idx, size_t n, Type c);\ | |
92 | +int Name##_replace(Name *self, size_t idx, size_t len, Type *cstr, size_t cstr_len);\ | |
93 | +int Name##_replace_c(Name *self, size_t idx, size_t len, size_t n, Type c);\ | |
94 | +size_t Name##_find(Type *x, Type *cstr, size_t idx, size_t cstr_len);\ | |
95 | +size_t Name##_find_c(Type *x, Type c, size_t idx);\ | |
96 | +size_t Name##_rfind(Type *x, Type *cstr, size_t idx, size_t cstr_len);\ | |
97 | +size_t Name##_rfind_c(Type *x, Type c, size_t idx);\ | |
98 | +size_t Name##_find_first_of(Type *x, Type *cstr, size_t idx, size_t cstr_len);\ | |
99 | +size_t Name##_find_first_of_c(Type *x, Type c, size_t idx);\ | |
100 | +size_t Name##_find_last_of(Type *x, Type *cstr, size_t idx, size_t cstr_len);\ | |
101 | +size_t Name##_find_last_of_c(Type *x, Type c, size_t idx);\ | |
102 | +size_t Name##_find_first_not_of(Type *x, Type *cstr, size_t idx, size_t cstr_len);\ | |
103 | +size_t Name##_find_first_not_of_c(Type *x, Type c, size_t idx);\ | |
104 | +size_t Name##_find_last_not_of(Type *x, Type *cstr, size_t idx, size_t cstr_len);\ | |
105 | +size_t Name##_find_last_not_of_c(Type *x, Type c, size_t idx);\ | |
106 | +STRING_END_EXTERN_C()\ | |
107 | + | |
108 | + | |
109 | +/*! | |
110 | + * \brief 実装マクロ | |
111 | + * | |
112 | + * \param Name コンテナ名 | |
113 | + * \param Type 要素の型 | |
114 | + */ | |
115 | +#define STRING_IMPLEMENT(Name, Type) \ | |
116 | +\ | |
117 | +static int Name##my_memcmp(const Type *x, const Type *y, size_t size)\ | |
118 | +{\ | |
119 | + if (size) {\ | |
120 | + do {\ | |
121 | + if (*x != *y) {\ | |
122 | + return *x - *y;\ | |
123 | + }\ | |
124 | + x++;\ | |
125 | + y++;\ | |
126 | + size--;\ | |
127 | + } while (size);\ | |
128 | + }\ | |
129 | + return 0;\ | |
130 | +}\ | |
131 | +\ | |
132 | +static size_t Name##my_strlen(const Type *cstr)\ | |
133 | +{\ | |
134 | + size_t i = 0;\ | |
135 | + while (*cstr != '\0') {\ | |
136 | + cstr++;\ | |
137 | + i++;\ | |
138 | + }\ | |
139 | + return i;\ | |
140 | +}\ | |
141 | +\ | |
142 | +VECTOR_INTERFACE(Name##CharVector, Type)\ | |
143 | +VECTOR_IMPLEMENT(Name##CharVector, Type)\ | |
144 | +\ | |
145 | +/*! | |
146 | + * \brief string構造体 | |
147 | + */\ | |
148 | +struct Name##_t {\ | |
149 | + Name##CharVector *data;\ | |
150 | + STRING_MAGIC(void *magic;)\ | |
151 | +};\ | |
152 | +\ | |
153 | +\ | |
154 | +Name *Name##_new(void)\ | |
155 | +{\ | |
156 | + Name *self;\ | |
157 | + self = (Name *) malloc(sizeof(Name));\ | |
158 | + if (!self) return 0;\ | |
159 | + self->data = Name##CharVector_new();\ | |
160 | + if (!self->data) {\ | |
161 | + free(self);\ | |
162 | + return 0;\ | |
163 | + }\ | |
164 | + Name##CharVector_push_back(self->data, '\0');\ | |
165 | + STRING_MAGIC(self->magic = self);\ | |
166 | + return self;\ | |
167 | +}\ | |
168 | +\ | |
169 | +Name *Name##_new_cstr(Type *cstr, size_t cstr_len)\ | |
170 | +{\ | |
171 | + Name *self;\ | |
172 | + assert(cstr && "String_new_cstr");\ | |
173 | + self = (Name *) malloc(sizeof(Name));\ | |
174 | + if (!self) return 0;\ | |
175 | + if (cstr_len == NPOS) {\ | |
176 | + cstr_len = Name##my_strlen(cstr);\ | |
177 | + }\ | |
178 | + self->data = Name##CharVector_new_reserve(cstr_len +1);\ | |
179 | + if (!self->data) {\ | |
180 | + free(self);\ | |
181 | + return 0;\ | |
182 | + }\ | |
183 | + Name##CharVector_assign(self->data, cstr, cstr_len);\ | |
184 | + Name##CharVector_push_back(self->data, '\0');\ | |
185 | + STRING_MAGIC(self->magic = self);\ | |
186 | + return self;\ | |
187 | +}\ | |
188 | +\ | |
189 | +Name *Name##_new_c(size_t n, Type c)\ | |
190 | +{\ | |
191 | + Name *self;\ | |
192 | + self = (Name *) malloc(sizeof(Name));\ | |
193 | + if (!self) return 0;\ | |
194 | + self->data = Name##CharVector_new_reserve(n+1);\ | |
195 | + if (!self->data) {\ | |
196 | + free(self);\ | |
197 | + return 0;\ | |
198 | + }\ | |
199 | + STRING_MAGIC(self->magic = self);\ | |
200 | + Name##_assign_c(self, n, c);\ | |
201 | + return self;\ | |
202 | +}\ | |
203 | +\ | |
204 | +Name *Name##_new_copy(Name *x)\ | |
205 | +{\ | |
206 | + assert(x && "String_new_copy");\ | |
207 | + assert(x->magic == x && "String_new_copy");\ | |
208 | + return Name##_new_cstr(Name##_at(x, 0), Name##_size(x));\ | |
209 | +}\ | |
210 | +\ | |
211 | +void Name##_delete(Name *self)\ | |
212 | +{\ | |
213 | + assert(self && "String_delete");\ | |
214 | + assert(self->magic == self && "String_delete");\ | |
215 | + STRING_MAGIC(self->magic = 0);\ | |
216 | + Name##CharVector_delete(self->data);\ | |
217 | + free(self);\ | |
218 | +}\ | |
219 | +\ | |
220 | +void Name##_clear(Name *self)\ | |
221 | +{\ | |
222 | + assert(self && "String_clear");\ | |
223 | + assert(self->magic == self && "String_clear");\ | |
224 | + Name##CharVector_clear(self->data);\ | |
225 | + Name##CharVector_push_back(self->data, '\0');\ | |
226 | +}\ | |
227 | +\ | |
228 | +size_t Name##_size(Name *self)\ | |
229 | +{\ | |
230 | + assert(self && "String_size");\ | |
231 | + assert(self->magic == self && "String_size");\ | |
232 | + return Name##CharVector_size(self->data) -1;\ | |
233 | +}\ | |
234 | +\ | |
235 | +size_t Name##_length(Name *self)\ | |
236 | +{\ | |
237 | + assert(self && "String_length");\ | |
238 | + assert(self->magic == self && "String_length");\ | |
239 | + return Name##CharVector_size(self->data) -1;\ | |
240 | +}\ | |
241 | +\ | |
242 | +size_t Name##_capacity(Name *self)\ | |
243 | +{\ | |
244 | + assert(self && "String_capacity");\ | |
245 | + assert(self->magic == self && "String_capacity");\ | |
246 | + return Name##CharVector_capacity(self->data) -1;\ | |
247 | +}\ | |
248 | +\ | |
249 | +int Name##_reserve(Name *self, size_t n)\ | |
250 | +{\ | |
251 | + assert(self && "String_reserve");\ | |
252 | + assert(self->magic == self && "String_reserve");\ | |
253 | + return Name##CharVector_reserve(self->data, n +1);\ | |
254 | +}\ | |
255 | +\ | |
256 | +void Name##_shrink(Name *self, size_t n)\ | |
257 | +{\ | |
258 | + assert(self && "String_shrink");\ | |
259 | + assert(self->magic == self && "String_shrink");\ | |
260 | + Name##CharVector_shrink(self->data, n +1);\ | |
261 | +}\ | |
262 | +\ | |
263 | +int Name##_empty(Name *self)\ | |
264 | +{\ | |
265 | + assert(self && "String_empty");\ | |
266 | + assert(self->magic == self && "String_empty");\ | |
267 | + return Name##CharVector_size(self->data) == 1;\ | |
268 | +}\ | |
269 | +\ | |
270 | +int Name##_compare(Name *x, Name *y)\ | |
271 | +{\ | |
272 | + size_t xlen, ylen;\ | |
273 | + int ret;\ | |
274 | + assert(x && "String_compare");\ | |
275 | + assert(y && "String_compare");\ | |
276 | + assert(x->magic == x && "String_compare");\ | |
277 | + assert(y->magic == y && "String_compare");\ | |
278 | + xlen = Name##_size(x);\ | |
279 | + ylen = Name##_size(y);\ | |
280 | + ret = Name##my_memcmp(Name##_c_str(x), Name##_c_str(y), (xlen - ylen >= 0) ? ylen : xlen);\ | |
281 | + return ret ? ret : xlen - ylen;\ | |
282 | +}\ | |
283 | +\ | |
284 | +Type *Name##_at(Name *self, size_t idx)\ | |
285 | +{\ | |
286 | + assert(self && "String_at");\ | |
287 | + assert(self->magic == self && "String_at");\ | |
288 | + assert(Name##_size(self) > idx && "String_at");\ | |
289 | + return Name##CharVector_at(self->data, idx);\ | |
290 | +}\ | |
291 | +\ | |
292 | +Type *Name##_c_str(Name *self)\ | |
293 | +{\ | |
294 | + assert(self && "String_c_str");\ | |
295 | + assert(self->magic == self && "String_c_str");\ | |
296 | + return Name##CharVector_at(self->data, 0);\ | |
297 | +}\ | |
298 | +\ | |
299 | +void Name##_erase(Name *self, size_t idx, size_t len)\ | |
300 | +{\ | |
301 | + size_t size;\ | |
302 | + assert(self && "String_erase");\ | |
303 | + assert(self->magic == self && "String_erase");\ | |
304 | + size = Name##_size(self);\ | |
305 | + assert(size >= idx && "String_erase");\ | |
306 | + if (len > size - idx) {\ | |
307 | + len = size - idx;\ | |
308 | + }\ | |
309 | + Name##CharVector_erase_n(self->data, idx, len);\ | |
310 | +}\ | |
311 | +\ | |
312 | +int Name##_resize(Name *self, size_t n, Type c)\ | |
313 | +{\ | |
314 | + size_t num;\ | |
315 | + assert(self && "String_resize");\ | |
316 | + assert(self->magic == self && "String_resize");\ | |
317 | + num = Name##CharVector_size(self->data) -1;\ | |
318 | + if (!Name##CharVector_resize(self->data, n +1, c)) {\ | |
319 | + return 0;\ | |
320 | + }\ | |
321 | + if (num < Name##CharVector_size(self->data)) {\ | |
322 | + /* '\0'を上書き */\ | |
323 | + *Name##CharVector_at(self->data, num) = c;\ | |
324 | + }\ | |
325 | + *Name##CharVector_at(self->data, Name##CharVector_size(self->data) -1) = '\0';\ | |
326 | + return 1;\ | |
327 | +}\ | |
328 | +\ | |
329 | +int Name##_assign(Name *self, Type *cstr, size_t cstr_len)\ | |
330 | +{\ | |
331 | + assert(self && "String_assign");\ | |
332 | + assert(self->magic == self && "String_assign");\ | |
333 | + assert(cstr && "String_assign");\ | |
334 | + if (cstr_len == NPOS) {\ | |
335 | + cstr_len = Name##my_strlen(cstr);\ | |
336 | + }\ | |
337 | + if (!Name##CharVector_reserve(self->data, cstr_len +1)) {\ | |
338 | + return 0;\ | |
339 | + }\ | |
340 | + Name##CharVector_assign(self->data, cstr, cstr_len);\ | |
341 | + Name##CharVector_push_back(self->data, '\0');\ | |
342 | + return 1;\ | |
343 | +}\ | |
344 | +\ | |
345 | +int Name##_assign_c(Name *self, size_t n, Type c)\ | |
346 | +{\ | |
347 | + size_t i;\ | |
348 | + assert(self && "String_assign_c");\ | |
349 | + assert(self->magic == self && "String_assign_c");\ | |
350 | + if (!Name##_reserve(self, n)) {\ | |
351 | + return 0;\ | |
352 | + }\ | |
353 | + Name##_clear(self);\ | |
354 | + for (i = 0; i < n; i++) {\ | |
355 | + Name##_push_back(self, c);\ | |
356 | + }\ | |
357 | + return 1;\ | |
358 | +}\ | |
359 | +\ | |
360 | +int Name##_append(Name *self, Type *cstr, size_t cstr_len)\ | |
361 | +{\ | |
362 | + assert(self && "String_append");\ | |
363 | + assert(self->magic == self && "String_append");\ | |
364 | + assert(cstr && "String_append");\ | |
365 | + if (cstr_len == NPOS) {\ | |
366 | + cstr_len = Name##my_strlen(cstr);\ | |
367 | + }\ | |
368 | + return Name##CharVector_insert_n(self->data, Name##CharVector_size(self->data)-1, cstr, cstr_len);\ | |
369 | +}\ | |
370 | +\ | |
371 | +int Name##_append_c(Name *self, size_t n, Type c)\ | |
372 | +{\ | |
373 | + size_t i;\ | |
374 | + assert(self && "String_append_c");\ | |
375 | + assert(self->magic == self && "String_append_c");\ | |
376 | + if (!Name##_reserve(self, Name##_size(self) + n)) {\ | |
377 | + return 0;\ | |
378 | + }\ | |
379 | + for (i = 0; i < n; i++) {\ | |
380 | + Name##_push_back(self, c);\ | |
381 | + }\ | |
382 | + return 1;\ | |
383 | +}\ | |
384 | +\ | |
385 | +int Name##_push_back(Name *self, Type c)\ | |
386 | +{\ | |
387 | + assert(self && "String_push_back");\ | |
388 | + assert(self->magic == self && "String_push_back");\ | |
389 | + return Name##CharVector_insert(self->data, Name##CharVector_size(self->data)-1, c);\ | |
390 | +}\ | |
391 | +\ | |
392 | +int Name##_insert(Name *self, size_t idx, Type *cstr, size_t cstr_len)\ | |
393 | +{\ | |
394 | + assert(self && "String_insert");\ | |
395 | + assert(self->magic == self && "String_insert");\ | |
396 | + assert(Name##_size(self) >= idx && "String_insert");\ | |
397 | + assert(cstr && "String_insert");\ | |
398 | + if (cstr_len == NPOS) {\ | |
399 | + cstr_len = Name##my_strlen(cstr);\ | |
400 | + }\ | |
401 | + return Name##CharVector_insert_n(self->data, idx, cstr, cstr_len);\ | |
402 | +}\ | |
403 | +\ | |
404 | +int Name##_insert_c(Name *self, size_t idx, size_t n, Type c)\ | |
405 | +{\ | |
406 | + size_t i;\ | |
407 | + assert(self && "String_insert_c");\ | |
408 | + assert(self->magic == self && "String_insert_c");\ | |
409 | + assert(Name##_size(self) >= idx && "String_insert_c");\ | |
410 | + if (!Name##_reserve(self, Name##_size(self) + n)) {\ | |
411 | + return 0;\ | |
412 | + }\ | |
413 | + for (i = 0; i < n; i++) {\ | |
414 | + Name##CharVector_insert(self->data, idx, c);\ | |
415 | + idx++;\ | |
416 | + }\ | |
417 | + return 1;\ | |
418 | +}\ | |
419 | +\ | |
420 | +int Name##_replace(Name *self, size_t idx, size_t len, Type *cstr, size_t cstr_len)\ | |
421 | +{\ | |
422 | + size_t i;\ | |
423 | + size_t size;\ | |
424 | + assert(self && "String_replace");\ | |
425 | + assert(self->magic == self && "String_replace");\ | |
426 | + assert(cstr && "String_replace");\ | |
427 | + size = Name##_size(self);\ | |
428 | + assert(size >= idx && "String_replace");\ | |
429 | + if (len > size - idx) {\ | |
430 | + len = size - idx;\ | |
431 | + }\ | |
432 | + if (cstr_len == NPOS) {\ | |
433 | + cstr_len = Name##my_strlen(cstr);\ | |
434 | + }\ | |
435 | + if (cstr_len <= len) {\ | |
436 | + /* 拡張必要なし */\ | |
437 | + for (i = 0; i < len; i++) {\ | |
438 | + if (i < cstr_len) {\ | |
439 | + *Name##_at(self, i + idx) = cstr[i];\ | |
440 | + } else {\ | |
441 | + size_t j = len - cstr_len;\ | |
442 | + if (j > Name##_size(self) - (cstr_len + idx)) {\ | |
443 | + j = Name##_size(self) - (cstr_len + idx);\ | |
444 | + }\ | |
445 | + Name##_erase(self, cstr_len + idx, j);\ | |
446 | + break;\ | |
447 | + }\ | |
448 | + }\ | |
449 | + } else {\ | |
450 | + /* 拡張必要あり */\ | |
451 | + if (!Name##_reserve(self, Name##_capacity(self) + (cstr_len - len))) {\ | |
452 | + return 0;\ | |
453 | + }\ | |
454 | + for (i = 0; i < len; i++) {\ | |
455 | + *Name##_at(self, i + idx) = cstr[i];\ | |
456 | + }\ | |
457 | + Name##_insert(self, len + idx, &cstr[len], cstr_len - len);\ | |
458 | + }\ | |
459 | + return 1;\ | |
460 | +}\ | |
461 | +\ | |
462 | +int Name##_replace_c(Name *self, size_t idx, size_t len, size_t n, Type c)\ | |
463 | +{\ | |
464 | + size_t i;\ | |
465 | + size_t size;\ | |
466 | + assert(self && "String_replace_c");\ | |
467 | + assert(self->magic == self && "String_replace_c");\ | |
468 | + size = Name##_size(self);\ | |
469 | + assert(size >= idx && "String_replace_c");\ | |
470 | + if (len > size - idx) {\ | |
471 | + len = size - idx;\ | |
472 | + }\ | |
473 | + assert(Name##_size(self) >= idx + len && "String_replace_c");\ | |
474 | + if (n <= len) {\ | |
475 | + /* 拡張必要なし */\ | |
476 | + for (i = 0; i < len; i++) {\ | |
477 | + if (i < n) {\ | |
478 | + *Name##_at(self, i + idx) = c;\ | |
479 | + } else {\ | |
480 | + size_t j = len - n;\ | |
481 | + if (j > Name##_size(self) - (n + idx)) {\ | |
482 | + j = Name##_size(self) - (n + idx);\ | |
483 | + }\ | |
484 | + Name##_erase(self, n + idx, j);\ | |
485 | + break;\ | |
486 | + }\ | |
487 | + }\ | |
488 | + } else {\ | |
489 | + /* 拡張必要あり */\ | |
490 | + if (!Name##_reserve(self, Name##_capacity(self) + (n - len))) {\ | |
491 | + return 0;\ | |
492 | + }\ | |
493 | + for (i = 0; i < len; i++) {\ | |
494 | + *Name##_at(self, i + idx) = c;\ | |
495 | + }\ | |
496 | + Name##_insert_c(self, len + idx, n - len, c);\ | |
497 | + }\ | |
498 | + return 1;\ | |
499 | +}\ | |
500 | +\ | |
501 | +static size_t Name##_brute_force_search(Type *str, size_t str_len, Type *ptn, size_t ptn_len)\ | |
502 | +{\ | |
503 | + size_t i = 0;\ | |
504 | + size_t j = 0;\ | |
505 | +\ | |
506 | + if (str_len < ptn_len) return NPOS;\ | |
507 | + while (i < str_len && j < ptn_len) {\ | |
508 | + if (str[i] == ptn[j]) {\ | |
509 | + i++;\ | |
510 | + j++;\ | |
511 | + } else {\ | |
512 | + i += 1 - j;\ | |
513 | + j = 0;\ | |
514 | + }\ | |
515 | + }\ | |
516 | + return (j == ptn_len) ? i - j : NPOS;\ | |
517 | +}\ | |
518 | +\ | |
519 | +static size_t Name##_brute_force_search_r(Type *str, size_t str_len, Type *ptn, size_t ptn_len)\ | |
520 | +{\ | |
521 | + size_t i = str_len;\ | |
522 | + size_t j = ptn_len;\ | |
523 | +\ | |
524 | + if (str_len < ptn_len) return NPOS;\ | |
525 | + while (i > 0 && j > 0) {\ | |
526 | + if (str[i-1] == ptn[j-1]) {\ | |
527 | + i--;\ | |
528 | + j--;\ | |
529 | + } else {\ | |
530 | + i += ptn_len - j - 1;\ | |
531 | + j = ptn_len;\ | |
532 | + }\ | |
533 | + }\ | |
534 | + return (j == 0) ? i : NPOS;\ | |
535 | +}\ | |
536 | +\ | |
537 | +size_t Name##_find(Type *x, Type *cstr, size_t idx, size_t cstr_len)\ | |
538 | +{\ | |
539 | + size_t i;\ | |
540 | + size_t size;\ | |
541 | + assert(x && "String_find");\ | |
542 | + assert(cstr && "String_find");\ | |
543 | + if (cstr_len == NPOS) {\ | |
544 | + cstr_len = Name##my_strlen(cstr);\ | |
545 | + }\ | |
546 | + if (cstr_len == 0) {\ | |
547 | + return idx;\ | |
548 | + }\ | |
549 | + size = Name##my_strlen(x);\ | |
550 | + if (size < idx) return NPOS;\ | |
551 | + i = Name##_brute_force_search(&x[idx], size - idx, cstr, cstr_len);\ | |
552 | + if (i == NPOS) return i;\ | |
553 | + return i + idx;\ | |
554 | +}\ | |
555 | +\ | |
556 | +size_t Name##_find_c(Type *x, Type c, size_t idx)\ | |
557 | +{\ | |
558 | + assert(x && "String_find_c");\ | |
559 | + return Name##_find(x, &c, idx, 1);\ | |
560 | +}\ | |
561 | +\ | |
562 | +size_t Name##_rfind(Type *x, Type *cstr, size_t idx, size_t cstr_len)\ | |
563 | +{\ | |
564 | + size_t size;\ | |
565 | + assert(x && "String_rfind");\ | |
566 | + assert(cstr && "String_rfind");\ | |
567 | + if (cstr_len == NPOS) {\ | |
568 | + cstr_len = Name##my_strlen(cstr);\ | |
569 | + }\ | |
570 | + size = Name##my_strlen(x);\ | |
571 | + if (size - cstr_len < idx) {\ | |
572 | + idx = size - cstr_len;\ | |
573 | + }\ | |
574 | + return Name##_brute_force_search_r(&x[0], idx + cstr_len, cstr, cstr_len);\ | |
575 | +}\ | |
576 | +\ | |
577 | +size_t Name##_rfind_c(Type *x, Type c, size_t idx)\ | |
578 | +{\ | |
579 | + assert(x && "String_rfind_c");\ | |
580 | + return Name##_rfind(x, &c, idx, 1);\ | |
581 | +}\ | |
582 | +\ | |
583 | +size_t Name##_find_first_of(Type *x, Type *cstr, size_t idx, size_t cstr_len)\ | |
584 | +{\ | |
585 | + size_t i, j;\ | |
586 | + size_t size;\ | |
587 | + assert(x && "String_find_first_of");\ | |
588 | + assert(cstr && "String_find_first_of");\ | |
589 | + size = Name##my_strlen(x);\ | |
590 | + if (size < idx) return NPOS;\ | |
591 | + if (cstr_len == NPOS) {\ | |
592 | + cstr_len = Name##my_strlen(cstr);\ | |
593 | + }\ | |
594 | + for (i = idx; i < size; i++) {\ | |
595 | + for (j = 0; j < cstr_len; j++) {\ | |
596 | + if (x[i] == cstr[j]) {\ | |
597 | + return i;\ | |
598 | + }\ | |
599 | + }\ | |
600 | + }\ | |
601 | + return NPOS;\ | |
602 | +}\ | |
603 | +\ | |
604 | +size_t Name##_find_first_of_c(Type *x, Type c, size_t idx)\ | |
605 | +{\ | |
606 | + assert(x && "String_find_first_of_c");\ | |
607 | + return Name##_find_first_of(x, &c, idx, 1);\ | |
608 | +}\ | |
609 | +\ | |
610 | +size_t Name##_find_last_of(Type *x, Type *cstr, size_t idx, size_t cstr_len)\ | |
611 | +{\ | |
612 | + size_t i, j;\ | |
613 | + size_t size;\ | |
614 | + assert(x && "String_find_last_of");\ | |
615 | + assert(cstr && "String_find_last_of");\ | |
616 | + size = Name##my_strlen(x);\ | |
617 | + if (size <= idx) {\ | |
618 | + idx = size -1;\ | |
619 | + }\ | |
620 | + if (cstr_len == NPOS) {\ | |
621 | + cstr_len = Name##my_strlen(cstr);\ | |
622 | + }\ | |
623 | + for (i = idx +1; i > 0; i--) {\ | |
624 | + for (j = 0; j < cstr_len; j++) {\ | |
625 | + if (x[i-1] == cstr[j]) {\ | |
626 | + return i-1;\ | |
627 | + }\ | |
628 | + }\ | |
629 | + }\ | |
630 | + return NPOS;\ | |
631 | +}\ | |
632 | +\ | |
633 | +size_t Name##_find_last_of_c(Type *x, Type c, size_t idx)\ | |
634 | +{\ | |
635 | + assert(x && "String_find_last_of_c");\ | |
636 | + return Name##_find_last_of(x, &c, idx, 1);\ | |
637 | +}\ | |
638 | +\ | |
639 | +size_t Name##_find_first_not_of(Type *x, Type *cstr, size_t idx, size_t cstr_len)\ | |
640 | +{\ | |
641 | + size_t i, j;\ | |
642 | + size_t size;\ | |
643 | + assert(x && "String_find_first_not_of");\ | |
644 | + assert(cstr && "String_find_first_not_of");\ | |
645 | + size = Name##my_strlen(x);\ | |
646 | + if (size < idx) return NPOS;\ | |
647 | + if (cstr_len == NPOS) {\ | |
648 | + cstr_len = Name##my_strlen(cstr);\ | |
649 | + }\ | |
650 | + if (cstr_len == 0) {\ | |
651 | + return idx;\ | |
652 | + }\ | |
653 | + for (i = idx; i < size; i++) {\ | |
654 | + for (j = 0; j < cstr_len; j++) {\ | |
655 | + if (x[i] != cstr[j]) {\ | |
656 | + if (j == cstr_len - 1) return i;\ | |
657 | + } else {\ | |
658 | + break;\ | |
659 | + }\ | |
660 | + }\ | |
661 | + }\ | |
662 | + return NPOS;\ | |
663 | +}\ | |
664 | +\ | |
665 | +size_t Name##_find_first_not_of_c(Type *x, Type c, size_t idx)\ | |
666 | +{\ | |
667 | + assert(x && "String_find_first_not_of_c");\ | |
668 | + return Name##_find_first_not_of(x, &c, idx, 1);\ | |
669 | +}\ | |
670 | +\ | |
671 | +size_t Name##_find_last_not_of(Type *x, Type *cstr, size_t idx, size_t cstr_len)\ | |
672 | +{\ | |
673 | + size_t i, j;\ | |
674 | + size_t size;\ | |
675 | + assert(x && "String_find_last_not_of");\ | |
676 | + assert(cstr && "String_find_last_not_of");\ | |
677 | + size = Name##my_strlen(x);\ | |
678 | + if (size <= idx) {\ | |
679 | + idx = size -1;\ | |
680 | + }\ | |
681 | + if (cstr_len == NPOS) {\ | |
682 | + cstr_len = Name##my_strlen(cstr);\ | |
683 | + }\ | |
684 | + if (cstr_len == 0) {\ | |
685 | + return idx;\ | |
686 | + }\ | |
687 | + for (i = idx +1; i > 0; i--) {\ | |
688 | + for (j = 0; j < cstr_len; j++) {\ | |
689 | + if (x[i-1] != cstr[j]) {\ | |
690 | + if (j == cstr_len - 1) return i-1;\ | |
691 | + } else {\ | |
692 | + break;\ | |
693 | + }\ | |
694 | + }\ | |
695 | + }\ | |
696 | + return NPOS;\ | |
697 | +}\ | |
698 | +\ | |
699 | +size_t Name##_find_last_not_of_c(Type *x, Type c, size_t idx)\ | |
700 | +{\ | |
701 | + assert(x && "String_find_last_not_of_c");\ | |
702 | + return Name##_find_last_not_of(x, &c, idx, 1);\ | |
703 | +}\ | |
704 | +\ | |
705 | + | |
706 | + | |
707 | +#endif /* CSTL_STRING_H_INCLUDED */ |
@@ -0,0 +1 @@ | ||
1 | +<br> |
@@ -0,0 +1,405 @@ | ||
1 | +<STYLE> | |
2 | +BODY | |
3 | +{ | |
4 | + BACKGROUND-COLOR: #ffffff; | |
5 | + COLOR: #6495ED; | |
6 | + scrollbar-3d-light-color: #ffffff; | |
7 | + scrollbar-arrow-color: #6495ED; | |
8 | + scrollbar-base-color: #6495ED; | |
9 | + scrollbar-dark-shadow-color: #6495ED; | |
10 | + scrollbar-face-color: #ffffff; | |
11 | + scrollbar-highlight-color: #6495ED; | |
12 | + scrollbar-shadow-color: #6495ED | |
13 | +} | |
14 | +A:link | |
15 | +{ | |
16 | + COLOR: #6495ED | |
17 | +} | |
18 | +A:visited | |
19 | +{ | |
20 | + COLOR: #6495ED | |
21 | +} | |
22 | +A:hover | |
23 | +{ | |
24 | + COLOR: #ff0000 | |
25 | +} | |
26 | +A:active | |
27 | +{ | |
28 | + COLOR: #ff0000 | |
29 | +} | |
30 | +TD | |
31 | +{ | |
32 | + COLOR: #6495ED; | |
33 | + FONT-SIZE: 14px | |
34 | +} | |
35 | +TD A:link | |
36 | +{ | |
37 | + COLOR: #6495ED | |
38 | +} | |
39 | +TD A:hover | |
40 | +{ | |
41 | + COLOR: #ff0000 | |
42 | +} | |
43 | +TD A:active | |
44 | +{ | |
45 | + COLOR: #ff0000 | |
46 | +} | |
47 | +.footer | |
48 | +{ | |
49 | + FONT-SIZE: 0.8em | |
50 | +} | |
51 | +.backgr | |
52 | +{ | |
53 | + BACKGROUND-COLOR: #6495ED; | |
54 | + COLOR: #ffffff | |
55 | +} | |
56 | +.backgr A:active | |
57 | +{ | |
58 | + COLOR: #ff0000 | |
59 | +} | |
60 | +.backgr A:hover | |
61 | +{ | |
62 | + COLOR: #ff0000 | |
63 | +} | |
64 | +.backgr A:link | |
65 | +{ | |
66 | + COLOR: #ffffff | |
67 | +} | |
68 | +.backwh | |
69 | +{ | |
70 | + BACKGROUND-COLOR: #ffffff; | |
71 | + COLOR: #6495ED | |
72 | +} | |
73 | +.backwh A:active | |
74 | +{ | |
75 | + COLOR: #ff0000 | |
76 | +} | |
77 | +.backwh A:hover | |
78 | +{ | |
79 | + COLOR: #ff0000 | |
80 | +} | |
81 | +.backwh A:link | |
82 | +{ | |
83 | + COLOR: #6495ED | |
84 | +} | |
85 | +.text | |
86 | +{ | |
87 | + COLOR: #333333; | |
88 | + FONT-SIZE: 14px; | |
89 | + LINE-HEIGHT: 1.2em | |
90 | +} | |
91 | +.title | |
92 | +{ | |
93 | + BACKGROUND-COLOR: #6495ED; | |
94 | + BORDER-BOTTOM-WIDTH: 1px; | |
95 | + BORDER-LEFT-WIDTH: 1px; | |
96 | + BORDER-RIGHT-WIDTH: 1px; | |
97 | + BORDER-TOP-WIDTH: 1px; | |
98 | + COLOR: #ffffff; | |
99 | + FLOAT: none; | |
100 | + FONT-SIZE: 1.2em; | |
101 | + FONT-WEIGHT: bold; | |
102 | + MARGIN: 10px 2px; | |
103 | + PADDING-BOTTOM: 2px; | |
104 | + PADDING-LEFT: 2px; | |
105 | + PADDING-RIGHT: 2px; | |
106 | + PADDING-TOP: 2px; | |
107 | + WIDTH: 100% | |
108 | +} | |
109 | +B | |
110 | +{ | |
111 | + FONT-WEIGHT: bold | |
112 | +} | |
113 | +.red | |
114 | +{ | |
115 | + COLOR: #ff0000 | |
116 | +} | |
117 | +.backgy | |
118 | +{ | |
119 | + BACKGROUND-COLOR: #cccccc; | |
120 | + COLOR: #ffffff | |
121 | +} | |
122 | +TD.list | |
123 | +{ | |
124 | + BACKGROUND-COLOR: #ffffff; | |
125 | + COLOR: #6495ED; | |
126 | + FONT-SIZE: 0.8em | |
127 | +} | |
128 | +.txtgr | |
129 | +{ | |
130 | + BACKGROUND-COLOR: #ffffff; | |
131 | + COLOR: #6495ED; | |
132 | + LINE-HEIGHT: 1.4em | |
133 | +} | |
134 | +.txtgy | |
135 | +{ | |
136 | + BACKGROUND-COLOR: #ffffff; | |
137 | + COLOR: #666666; | |
138 | + LINE-HEIGHT: 1.4em | |
139 | +} | |
140 | +.preparation | |
141 | +{ | |
142 | + BACKGROUND-COLOR: #cccccc; | |
143 | + BORDER-BOTTOM-WIDTH: 1px; | |
144 | + BORDER-LEFT-WIDTH: 1px; | |
145 | + BORDER-RIGHT-WIDTH: 1px; | |
146 | + BORDER-TOP-WIDTH: 1px; | |
147 | + COLOR: #ffffff; | |
148 | + FLOAT: none; | |
149 | + FONT-SIZE: 1.2em; | |
150 | + FONT-WEIGHT: bold; | |
151 | + MARGIN: 10px 2px; | |
152 | + PADDING-BOTTOM: 2px; | |
153 | + PADDING-LEFT: 2px; | |
154 | + PADDING-RIGHT: 2px; | |
155 | + PADDING-TOP: 2px; | |
156 | + WIDTH: 100% | |
157 | +} | |
158 | +TD.listpp | |
159 | +{ | |
160 | + BACKGROUND-COLOR: #ffffff; | |
161 | + COLOR: #cccccc; | |
162 | + FONT-SIZE: 0.8em | |
163 | +} | |
164 | +.big | |
165 | +{ | |
166 | + FONT-SIZE: 1.2em | |
167 | +} | |
168 | +.small | |
169 | +{ | |
170 | + FONT-SIZE: 0.9em | |
171 | +} | |
172 | +.smallold | |
173 | +{ | |
174 | + FONT-SIZE: 1em | |
175 | +} | |
176 | + | |
177 | +.bg14 | |
178 | +{ | |
179 | + FONT-SIZE: 1.4em | |
180 | +} | |
181 | +.backgy2 | |
182 | +{ | |
183 | + BACKGROUND-COLOR: #666666; | |
184 | + COLOR: #ffffff | |
185 | +} | |
186 | +.coution | |
187 | +{ | |
188 | + BACKGROUND-COLOR: #ffffff; | |
189 | + COLOR: #ff0000; | |
190 | + FONT-WEIGHT: bold | |
191 | +} | |
192 | +.backgy3 | |
193 | +{ | |
194 | + BACKGROUND-COLOR: #999999; | |
195 | + COLOR: #000000 | |
196 | +} | |
197 | +.small09 | |
198 | +{ | |
199 | + FONT-SIZE: 0.9em | |
200 | +} | |
201 | +.secret | |
202 | +{ | |
203 | + BACKGROUND-COLOR: #ffffff; | |
204 | + COLOR: #cccccc; | |
205 | + FONT-SIZE: 0.7em | |
206 | +} | |
207 | +.secret A:active | |
208 | +{ | |
209 | + COLOR: #ff0000 | |
210 | +} | |
211 | +.secret A:hover | |
212 | +{ | |
213 | + COLOR: #ff0000 | |
214 | +} | |
215 | +.secret A:link | |
216 | +{ | |
217 | + COLOR: #cccccc | |
218 | +} | |
219 | +.secret A:visited | |
220 | +{ | |
221 | + COLOR: #cccccc | |
222 | +} | |
223 | +.txtgy2 | |
224 | +{ | |
225 | + COLOR: #666666; | |
226 | + LINE-HEIGHT: 1.4em | |
227 | +} | |
228 | + | |
229 | + | |
230 | +/*--------------------*/ | |
231 | +/*横位置調節 */ | |
232 | +/*--------------------*/ | |
233 | +.space1 | |
234 | +{ | |
235 | + margin-top : 0.5em; | |
236 | + margin-left : 1.5em; | |
237 | + margin-right : 0.2em; | |
238 | + padding-top : 0.1em; | |
239 | + padding-left : 0.2em; | |
240 | +} | |
241 | +.space2 | |
242 | +{ | |
243 | + margin-top : 0.5em; | |
244 | + margin-left : 2.5em; | |
245 | + margin-right : 5em; | |
246 | + padding-top : 0.1em; | |
247 | + padding-left : 0.2em; | |
248 | +} | |
249 | +.space3 | |
250 | +{ | |
251 | + margin-top : 0.5em; | |
252 | + margin-left : 4em; | |
253 | + margin-right : 5em; | |
254 | + padding-top : 0.1em; | |
255 | + padding-left : 0.2em; | |
256 | +} | |
257 | +.space4 | |
258 | +{ | |
259 | + margin-top : 0.5em; | |
260 | + margin-left : 5em; | |
261 | + margin-right : 5em; | |
262 | + padding-top : 0.1em; | |
263 | + padding-left : 0.2em; | |
264 | +} | |
265 | + | |
266 | +/*--------------------*/ | |
267 | +/*タイトル部の書式指定*/ | |
268 | +/*--------------------*/ | |
269 | +H1, H2, H3, H4, H5, H6 { color: #6495ED } | |
270 | +H1 { | |
271 | + background : #DFD; | |
272 | + padding-left : 0.2em; | |
273 | + padding-top : 0.3em; | |
274 | + padding-bottom : 0.2em; | |
275 | + border-width : 0em 0em 0em 1em; | |
276 | + border-style : none none none solid; | |
277 | + border-color : #6495ED; | |
278 | +} | |
279 | +H1 EM { text-shadow: Blue 5 5 5 } | |
280 | +H2 { | |
281 | + FONT-SIZE : 1.4em; | |
282 | + margin-top : 0.5em; | |
283 | + margin-left : 0.2em; | |
284 | + padding-top : 0.1em; | |
285 | + padding-left : 0.2em; | |
286 | + border-width : 0em 0em 0.1em 0.1em; | |
287 | + border-style : none none solid solid; | |
288 | + border-color : #6495ED; | |
289 | +} | |
290 | +H3 { | |
291 | + margin-top : 0.5em; | |
292 | + margin-left : 0.4em; | |
293 | + padding-top : 0.1em; | |
294 | + padding-left : 0.2em; | |
295 | + border-width : 0em 0em 0.1em 0em; | |
296 | + border-style : none none solid none; | |
297 | + border-color : #6495ED; | |
298 | +} | |
299 | +H4 { | |
300 | + margin-top : 0.5em; | |
301 | + margin-left : 0.6em; | |
302 | + padding-top : 0.1em; | |
303 | + padding-left : 0.2em; | |
304 | + border-width : 0em 0em 0.1em 0em; | |
305 | + border-style : none none solid none; | |
306 | + border-color : #6495ED; | |
307 | +} | |
308 | +H5 { | |
309 | + margin-top : 0.5em; | |
310 | + margin-left : 0.8em; | |
311 | + padding-top : 0.1em; | |
312 | + padding-left : 0.2em; | |
313 | + border-width : 0em 0em 0.1em 0em; | |
314 | + border-style : none none solid none; | |
315 | + border-color : #6495ED; | |
316 | +} | |
317 | +H6 { | |
318 | + margin-top : 0.5em; | |
319 | + margin-left : 1.0em; | |
320 | + padding-top : 0.1em; | |
321 | + padding-left : 0.2em; | |
322 | + border-width : 0em 0em 0.1em 0em; | |
323 | + border-style : none none solid none; | |
324 | + border-color : #6495ED; | |
325 | +} | |
326 | + | |
327 | +/*----------------------------*/ | |
328 | +/*引用部のボックススタイル指定*/ | |
329 | +/*----------------------------*/ | |
330 | +PRE { | |
331 | + background : #E0FFFF; | |
332 | + border-color : #6495ED; | |
333 | + border-width : thin; | |
334 | + border-style : solid; | |
335 | + margin-right : 5em; | |
336 | + margin-left : 0.5em; | |
337 | + padding-top : 1em; | |
338 | + padding-bottom : 1em; | |
339 | + padding-left : 0.5em; | |
340 | + padding-right : 1em; | |
341 | +} | |
342 | + | |
343 | +.PointsArea { | |
344 | + border-style : none; | |
345 | + background : #FFF; | |
346 | + margin-top : 0.5em; | |
347 | + margin-left : 2.5em; | |
348 | + margin-right : 20em; | |
349 | + padding-top : 0em; | |
350 | + padding-left : 0em; | |
351 | +} | |
352 | +.SourceArea { | |
353 | + text-decoration : none; | |
354 | + font-style : Normal; | |
355 | + color : #CCF; | |
356 | + background : #000; | |
357 | + border-color : #5BB; | |
358 | + margin-top : 0.5em; | |
359 | + margin-left : 2.5em; | |
360 | + margin-right : 10em; | |
361 | + padding-top : 0.1em; | |
362 | + padding-left : 0.2em; | |
363 | +} | |
364 | +.ResultArea { | |
365 | + background : #DDF; | |
366 | + border-color : #55B; | |
367 | +} | |
368 | + | |
369 | +.Noumal { | |
370 | + background : #EEE; | |
371 | + border-color : Brack; | |
372 | +} | |
373 | + | |
374 | +/*------------------*/ | |
375 | +/*強調部のクラス分け*/ | |
376 | +/*------------------*/ | |
377 | +STRONG.KeyWord { color : #933 } | |
378 | +STRONG.Notice { | |
379 | + text-decoration : underline; | |
380 | + color : #933 | |
381 | +} | |
382 | +EM.Notice { | |
383 | + text-decoration : underline; | |
384 | + font-style : Normal; | |
385 | +} | |
386 | +CODE { | |
387 | + text-decoration : none; | |
388 | + font-style : Normal; | |
389 | + color : #CCF; | |
390 | +} | |
391 | + | |
392 | +UL | |
393 | +{ | |
394 | + margin-top : 0.4em; | |
395 | + margin-left : 1.0em; | |
396 | + margin-right : 0.2em; | |
397 | + padding-top : 0.1em; | |
398 | + padding-left : 0.2em; | |
399 | + LINE-HEIGHT: 1.6em | |
400 | +} | |
401 | +LI | |
402 | +{ | |
403 | + | |
404 | + LINE-HEIGHT: 1.6em | |
405 | +} |
@@ -0,0 +1,41 @@ | ||
1 | +# RD converter program setting | |
2 | +RD2 = rd2 | |
3 | +RD2OPT = -r rd/rd2html-lib --with-css=default.css | |
4 | +RD2HTML = $(RD2) $(RD2OPT) $(RD2HTMLOPT) | |
5 | +RMI2HTML = rmi2html.rb | |
6 | +RT2 = rt2 | |
7 | +RT2HTML = $(RT2) -r rt/rt2html-lib.rb $(RTOPT) $(RT2HTMLOPT) | |
8 | +HTML2TXT = w3m -e -dump -T text/html | |
9 | +TXT2RD = txt2rd $(TXT2RDOPT) | |
10 | + | |
11 | +# Files | |
12 | +__AllRDFiles__ = $(wildcard *.rd) | |
13 | +RDFiles = $(__AllRDFiles__:%.v.rd=) | |
14 | +RTFiles = $(wildcard *.rt) | |
15 | +GenerateFiles = $(HtmlByRD) $(TxtByRD) $(VerbRD) $(HtmlByRT) $(TxtByRT) | |
16 | +HtmlByRD = $(RDFiles:.rd=.html) | |
17 | +TxtByRD = $(RDFiles:.rd=.txt) | |
18 | +HtmlByRT = $(RTFiles:.rt=.html) | |
19 | +TxtByRT = $(RTFiles:.rt=.txt) | |
20 | + | |
21 | +# Rules | |
22 | +.PHONY: rd2html rd2txt txt2rd rt2html rt2txt clean | |
23 | +rd2html: $(HtmlByRD) | |
24 | +rd2txt: $(TxtByRD) | |
25 | +txt2rd: $(VerbRD) | |
26 | +rt2html: $(HtmlByRT) | |
27 | +rt2txt: $(TxtByRT) | |
28 | +clean: | |
29 | + rm -f *~ $(GenerateFiles) | |
30 | +%.html: %.rd | |
31 | + $(RD2HTML) $< > $@ || rm -f $@ | |
32 | +%.html: %.rt | |
33 | + $(RT2HTML) $< > $@ || rm -f $@ | |
34 | +%.txt: %.html | |
35 | + $(HTML2TXT) $< > $@ | |
36 | +%.v.rd: % | |
37 | + $(TXT2RD) $< > $@ | |
38 | +%.index.html: %.rd | |
39 | + $(RD2) -r rd/rd2rmi-lib -o $* $< | |
40 | + $(RMI2HTML) $*.rmi > $@ | |
41 | + |
@@ -0,0 +1,472 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2006, KATO Noriaki | |
3 | + * All rights reserved. | |
4 | + * | |
5 | + * Redistribution and use in source and binary forms, with or without | |
6 | + * modification, are permitted provided that the following conditions are met: | |
7 | + * | |
8 | + * 1. Redistributions of source code must retain the above copyright notice, | |
9 | + * this list of conditions and the following disclaimer. | |
10 | + * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + * this list of conditions and the following disclaimer in the documentation | |
12 | + * and/or other materials provided with the distribution. | |
13 | + * | |
14 | + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
15 | + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
18 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
20 | + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
21 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
22 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
23 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + */ | |
25 | +/*! | |
26 | + * \file heap.c | |
27 | + * \brief 動的メモリの確保と解放 | |
28 | + * \author KATO Noriaki <katono@users.sourceforge.jp> | |
29 | + * \date 2006-03-22 | |
30 | + */ | |
31 | + | |
32 | +#include <assert.h> | |
33 | +#include "heap.h" | |
34 | + | |
35 | + | |
36 | +#define HEADER_SIZE (sizeof(BlockHeader)) | |
37 | +#define SPLIT_MIN 16 /* 分割されたブロックの最小サイズ */ | |
38 | +#define MAGIC_NO 0x17 /* マジックナンバー */ | |
39 | + | |
40 | + | |
41 | +/*! | |
42 | + * \brief ヒープの初期化 | |
43 | + * \param self ヒープへのポインタ | |
44 | + * \param buf バッファへのポインタ | |
45 | + * \param size バッファのサイズ | |
46 | + */ | |
47 | +void Heap_init(Heap *self, void *buf, size_t size) | |
48 | +{ | |
49 | + BlockHeader *p = (BlockHeader *) buf; | |
50 | + | |
51 | + self->list_term.size = 0; | |
52 | + self->list_term.occupied = 1; | |
53 | + self->list_term.magic = ~MAGIC_NO; | |
54 | + self->list_term.next = p; | |
55 | +#ifndef SLIST_BLOCK | |
56 | + self->list_term.prev = p; | |
57 | +#endif | |
58 | + | |
59 | + p->size = size; | |
60 | + p->occupied = 0; | |
61 | + p->magic = MAGIC_NO; | |
62 | + p->next = &self->list_term; | |
63 | +#ifndef SLIST_BLOCK | |
64 | + p->prev = &self->list_term; | |
65 | +#endif | |
66 | + self->loop_p = &self->list_term; | |
67 | + | |
68 | + self->init_flag = self; | |
69 | +} | |
70 | + | |
71 | +/*! | |
72 | + * \brief メモリ確保 | |
73 | + * \param self ヒープへのポインタ | |
74 | + * \param size サイズ | |
75 | + * \param file 呼び出し側のファイル名 | |
76 | + * \param line 呼び出し側のファイルの行 | |
77 | + * \return 割り当てたメモリへのポインタ。失敗すると0が返る。 | |
78 | + */ | |
79 | +#ifdef HEAP_DEBUG | |
80 | +void *Heap_alloc_debug(Heap *self, size_t size, char *file, size_t line) | |
81 | +#else | |
82 | +void *Heap_alloc(Heap *self, size_t size) | |
83 | +#endif | |
84 | +{ | |
85 | + BlockHeader *p; | |
86 | + BlockHeader *s; | |
87 | + size_t alloc_block_size = HEADER_SIZE + size; | |
88 | + | |
89 | + if (self->init_flag != self) { | |
90 | + assert(0); | |
91 | + return 0; | |
92 | + } | |
93 | + for (p = self->loop_p->next; p != self->loop_p; p = p->next) { | |
94 | + if (!p->occupied && p->size >= alloc_block_size) { | |
95 | + if (p->size - alloc_block_size >= HEADER_SIZE + SPLIT_MIN) { | |
96 | + s = (BlockHeader *) ((unsigned char *) p + alloc_block_size); | |
97 | + s->size = p->size - alloc_block_size; | |
98 | + s->occupied = 0; | |
99 | + s->magic = MAGIC_NO; | |
100 | + p->size = alloc_block_size; | |
101 | + s->next = p->next; | |
102 | +#ifndef SLIST_BLOCK | |
103 | + s->prev = p; | |
104 | + p->next->prev = s; | |
105 | +#endif | |
106 | + p->next = s; | |
107 | + } | |
108 | + p->occupied = 1; | |
109 | +#ifdef HEAP_DEBUG | |
110 | + p->file = file; | |
111 | + p->line = line; | |
112 | +#endif | |
113 | + self->loop_p = p; | |
114 | + return (unsigned char *) p + HEADER_SIZE; | |
115 | + } | |
116 | + } | |
117 | + return 0; | |
118 | +} | |
119 | + | |
120 | +/*! | |
121 | + * \brief 既に確保したメモリのサイズ変更 | |
122 | + * \param self ヒープへのポインタ | |
123 | + * \param ptr 既に確保したメモリへのポインタ | |
124 | + * \param newsize 新しいサイズ | |
125 | + * \param file 呼び出し側のファイル名 | |
126 | + * \param line 呼び出し側のファイルの行 | |
127 | + * \return 新たに割り当てたメモリへのポインタ。失敗すると0が返る。 | |
128 | + */ | |
129 | +#ifdef HEAP_DEBUG | |
130 | +void *Heap_realloc_debug(Heap *self, void *ptr, size_t newsize, char *file, size_t line) | |
131 | +#else | |
132 | +void *Heap_realloc(Heap *self, void *ptr, size_t newsize) | |
133 | +#endif | |
134 | +{ | |
135 | + BlockHeader *p; | |
136 | + BlockHeader *s; | |
137 | + size_t new_alloc_block_size; | |
138 | + if (self->init_flag != self) { | |
139 | + assert(0); | |
140 | + return 0; | |
141 | + } | |
142 | + if (!ptr) { | |
143 | +#ifdef HEAP_DEBUG | |
144 | + return Heap_alloc_debug(self, newsize, file, line); | |
145 | +#else | |
146 | + return Heap_alloc(self, newsize); | |
147 | +#endif | |
148 | + } | |
149 | + if (!newsize) { | |
150 | + Heap_free(self, ptr); | |
151 | + return 0; | |
152 | + } | |
153 | + p = (BlockHeader *) ((unsigned char *) ptr - HEADER_SIZE); | |
154 | + if (p->magic != MAGIC_NO || !p->occupied) return 0; | |
155 | + new_alloc_block_size = newsize + HEADER_SIZE; | |
156 | + if (p->size >= new_alloc_block_size) { | |
157 | + if (p->size >= 2 * new_alloc_block_size && newsize >= SPLIT_MIN) { | |
158 | + /* 縮んだ分を空き領域として回収 */ | |
159 | + s = (BlockHeader *) ((unsigned char *) p + new_alloc_block_size); | |
160 | + s->occupied = 0; | |
161 | + s->magic = MAGIC_NO; | |
162 | +#ifndef SLIST_BLOCK | |
163 | + s->prev = p; | |
164 | +#endif | |
165 | + if (p->next->occupied) { | |
166 | + s->size = p->size - new_alloc_block_size; | |
167 | + s->next = p->next; | |
168 | +#ifndef SLIST_BLOCK | |
169 | + p->next->prev = s; | |
170 | +#endif | |
171 | + } else { | |
172 | + if (self->loop_p == p->next) { | |
173 | + self->loop_p = p->next->next; | |
174 | + } | |
175 | + s->size = p->size - new_alloc_block_size + p->next->size; | |
176 | + s->next = p->next->next; | |
177 | +#ifndef SLIST_BLOCK | |
178 | + p->next->next->prev = s; | |
179 | +#endif | |
180 | + } | |
181 | + p->size = new_alloc_block_size; | |
182 | + p->next = s; | |
183 | + } | |
184 | + return ptr; | |
185 | + } | |
186 | + if (p->next->occupied || p->size + p->next->size < new_alloc_block_size) { | |
187 | + size_t i; | |
188 | +#ifdef HEAP_DEBUG | |
189 | + void *newptr = Heap_alloc_debug(self, newsize, file, line); | |
190 | +#else | |
191 | + void *newptr = Heap_alloc(self, newsize); | |
192 | +#endif | |
193 | + if (!newptr) { | |
194 | + return 0; | |
195 | + } | |
196 | + for (i = 0; i < p->size - HEADER_SIZE; i++) { | |
197 | + ((unsigned char *) newptr)[i] = ((unsigned char *) ptr)[i]; | |
198 | + } | |
199 | + Heap_free(self, ptr); | |
200 | + return newptr; | |
201 | + } | |
202 | + if (self->loop_p == p->next) { | |
203 | + self->loop_p = p->next->next; | |
204 | + } | |
205 | + if (p->size + p->next->size - new_alloc_block_size >= HEADER_SIZE + SPLIT_MIN) { | |
206 | + BlockHeader tmp = *p->next; | |
207 | + s = (BlockHeader *) ((unsigned char *) p + new_alloc_block_size); | |
208 | + s->size = p->size + p->next->size - new_alloc_block_size; | |
209 | + s->occupied = 0; | |
210 | + s->magic = MAGIC_NO; | |
211 | +#ifndef SLIST_BLOCK | |
212 | + s->prev = p; | |
213 | +#endif | |
214 | + s->next = tmp.next; | |
215 | + p->size = new_alloc_block_size; | |
216 | +#ifndef SLIST_BLOCK | |
217 | + tmp.next->prev = s; | |
218 | +#endif | |
219 | + p->next = s; | |
220 | + } else { | |
221 | + p->size = p->size + p->next->size; | |
222 | +#ifndef SLIST_BLOCK | |
223 | + p->next->next->prev = p; | |
224 | +#endif | |
225 | + p->next = p->next->next; | |
226 | + } | |
227 | +#ifdef HEAP_DEBUG | |
228 | + p->file = file; | |
229 | + p->line = line; | |
230 | +#endif | |
231 | + return ptr; | |
232 | +} | |
233 | + | |
234 | +/*! | |
235 | + * \brief メモリ解放 | |
236 | + * \param self ヒープへのポインタ | |
237 | + * \param ptr 解放されるメモリへのポインタ | |
238 | + */ | |
239 | +#ifdef SLIST_BLOCK | |
240 | +void Heap_free(Heap *self, void *ptr) | |
241 | +{ | |
242 | + BlockHeader *p; | |
243 | + BlockHeader *prev; | |
244 | + BlockHeader *pprev; | |
245 | + | |
246 | + if (self->init_flag != self) { | |
247 | + assert(0); | |
248 | + return; | |
249 | + } | |
250 | + if (!ptr) { | |
251 | + return; | |
252 | + } | |
253 | + prev = &self->list_term; | |
254 | + pprev = &self->list_term; | |
255 | + for (p = self->list_term.next; p != &self->list_term; p = p->next) { | |
256 | + if (p == (BlockHeader *) ((unsigned char *) ptr - HEADER_SIZE)) { | |
257 | + if (p->magic != MAGIC_NO || !p->occupied) { | |
258 | + assert(0); | |
259 | + return; | |
260 | + } | |
261 | + p->occupied = 0; | |
262 | + if (p == self->loop_p) { | |
263 | + self->loop_p = prev; | |
264 | + } | |
265 | + if (!prev->occupied) { | |
266 | + prev->next = p->next; | |
267 | + prev->size += p->size; | |
268 | + p = prev; | |
269 | + if (p == self->loop_p) { | |
270 | + self->loop_p = pprev; | |
271 | + } | |
272 | + } | |
273 | + if (!p->next->occupied) { | |
274 | + p->size += p->next->size; | |
275 | + p->next = p->next->next; | |
276 | + } | |
277 | + return; | |
278 | + } | |
279 | + pprev = prev; | |
280 | + prev = p; | |
281 | + } | |
282 | + assert(0); | |
283 | +} | |
284 | +#else | |
285 | +void Heap_free(Heap *self, void *ptr) | |
286 | +{ | |
287 | + BlockHeader *p; | |
288 | + BlockHeader *tmp; | |
289 | + | |
290 | + if (self->init_flag != self) { | |
291 | + assert(0); | |
292 | + return; | |
293 | + } | |
294 | + if (!ptr) { | |
295 | + return; | |
296 | + } | |
297 | + p = (BlockHeader *) ((unsigned char *) ptr - HEADER_SIZE); | |
298 | + if (p->magic != MAGIC_NO || !p->occupied) { | |
299 | + assert(0); | |
300 | + return; | |
301 | + } | |
302 | + p->occupied = 0; | |
303 | + if (p == self->loop_p) { | |
304 | + self->loop_p = p->prev; | |
305 | + } | |
306 | + if (!p->prev->occupied) { | |
307 | + tmp = p->prev; | |
308 | + tmp->next = p->next; | |
309 | + p->next->prev = tmp; | |
310 | + tmp->size += p->size; | |
311 | + p = tmp; | |
312 | + if (p == self->loop_p) { | |
313 | + self->loop_p = p->prev; | |
314 | + } | |
315 | + } | |
316 | + if (!p->next->occupied) { | |
317 | + tmp = p->next; | |
318 | + p->next = tmp->next; | |
319 | + tmp->next->prev = p; | |
320 | + p->size += tmp->size; | |
321 | + } | |
322 | +} | |
323 | +#endif | |
324 | + | |
325 | + | |
326 | +/* 以下、デバッグ用 */ | |
327 | +#ifdef HEAP_DEBUG | |
328 | +#include <stdio.h> | |
329 | +#include <ctype.h> | |
330 | +/*! | |
331 | + * \brief 16進ダンプ | |
332 | + * \param buf バッファ | |
333 | + * \param size バッファサイズ | |
334 | + */ | |
335 | +void hex_dump(void *buf, size_t size) | |
336 | +{ | |
337 | + size_t i; | |
338 | + size_t j; | |
339 | + unsigned char tmp[16]; | |
340 | + unsigned char *p; | |
341 | + p = (unsigned char *) buf; | |
342 | + for (i = 0; i < size; i++) { | |
343 | + if (i%16 == 0) { | |
344 | + printf("%p: ", &p[i]); | |
345 | + } | |
346 | + printf("%02x ", p[i]); | |
347 | + tmp[i%16] = p[i]; | |
348 | + if (i == size -1) { | |
349 | + for (j = i+1; j < i + (16 - i%16); j++) { | |
350 | + tmp[j%16] = ' '; | |
351 | + printf(" "); | |
352 | + } | |
353 | + i = j - 1; | |
354 | + } | |
355 | + if (i%16 == 15) { | |
356 | + printf(" "); | |
357 | + for (j = 0; j < 16; j++) { | |
358 | + if (isprint(tmp[j])) { | |
359 | + printf("%c", tmp[j]); | |
360 | + } else { | |
361 | + printf("."); | |
362 | + } | |
363 | + } | |
364 | + printf("\n"); | |
365 | + } | |
366 | + } | |
367 | +} | |
368 | + | |
369 | +/*! | |
370 | + * \brief メモリリークを検出する | |
371 | + * \param self ヒープへのポインタ | |
372 | + * \param dump 真ならばリークをダンプする | |
373 | + * \return メモリリークの検出個数 | |
374 | + */ | |
375 | +size_t dump_memory_leak(Heap *self, int dump) | |
376 | +{ | |
377 | + BlockHeader *p; | |
378 | + size_t n = 0; | |
379 | + size_t total = 0; | |
380 | + int flag = 0; | |
381 | + if (self->init_flag != self) { | |
382 | + assert(0); | |
383 | + return 0; | |
384 | + } | |
385 | + for (p = self->list_term.next; p != &self->list_term; p = p->next) { | |
386 | + if (p->occupied) { | |
387 | + if (!flag) { | |
388 | + printf("\ndetected memory leaks!\n"); | |
389 | + flag = 1; | |
390 | + } | |
391 | + if (dump || n < 10) { | |
392 | + printf("%s(%d): ", p->file, p->line); | |
393 | + printf("%d bytes\n", p->size - HEADER_SIZE); | |
394 | + } else if (n == 10) { | |
395 | + printf("...\n"); | |
396 | + } | |
397 | + if (dump) { | |
398 | + hex_dump((unsigned char *) p + HEADER_SIZE, p->size - HEADER_SIZE); | |
399 | + } | |
400 | + n++; | |
401 | + total += p->size - HEADER_SIZE; | |
402 | + } | |
403 | + } | |
404 | + printf("\ntotal memory leaks: %d bytes\n", total); | |
405 | + return n; | |
406 | +} | |
407 | + | |
408 | +/*! | |
409 | + * \brief メモリブロックをダンプする | |
410 | + * \param self ヒープへのポインタ | |
411 | + * \param ptr Heap_alloc()で取得したポインタ | |
412 | + */ | |
413 | +void dump_memory_block(Heap *self, void *ptr) | |
414 | +{ | |
415 | + BlockHeader *p; | |
416 | + | |
417 | + if (self->init_flag != self) { | |
418 | + assert(0); | |
419 | + return; | |
420 | + } | |
421 | + if (!ptr) goto NG_block; | |
422 | + p = (BlockHeader *) ((unsigned char *) ptr - HEADER_SIZE); | |
423 | + if (p->magic != MAGIC_NO) goto NG_block; | |
424 | + | |
425 | + if (p->occupied) { | |
426 | + printf("%s(%d): ", p->file, p->line); | |
427 | + } else { | |
428 | + printf("*** free ***: "); | |
429 | + } | |
430 | + printf("block(%d bytes): alloc(%d bytes)\n" | |
431 | + , p->size, p->size - HEADER_SIZE); | |
432 | +#ifdef SLIST_BLOCK | |
433 | + printf("next(%p)\n", p->next); | |
434 | +#else | |
435 | + printf("prev(%p): next(%p)\n", p->prev, p->next); | |
436 | +#endif | |
437 | + hex_dump((unsigned char *) p, HEADER_SIZE); | |
438 | + hex_dump((unsigned char *) p + HEADER_SIZE, p->size - HEADER_SIZE); | |
439 | + printf("\n"); | |
440 | + return; | |
441 | +NG_block: | |
442 | + printf("NG memory block: %p\n", p); | |
443 | + return; | |
444 | +} | |
445 | + | |
446 | +/*! | |
447 | + * \brief 全メモリブロックのリストをダンプする | |
448 | + * \param self ヒープへのポインタ | |
449 | + */ | |
450 | +void dump_memory_list(Heap *self) | |
451 | +{ | |
452 | + BlockHeader *p; | |
453 | + if (self->init_flag != self) { | |
454 | + assert(0); | |
455 | + return; | |
456 | + } | |
457 | + printf("\ndump_memory_list()\n"); | |
458 | + printf("block header size: %d bytes\n", HEADER_SIZE); | |
459 | + printf("block list terminator\n"); | |
460 | +#ifdef SLIST_BLOCK | |
461 | + printf("next(%p)\n", self->list_term.next); | |
462 | +#else | |
463 | + printf("prev(%p): next(%p)\n", self->list_term.prev, self->list_term.next); | |
464 | +#endif | |
465 | + hex_dump((unsigned char *) (&self->list_term), HEADER_SIZE); | |
466 | + printf("\n"); | |
467 | + for (p = self->list_term.next; p != &self->list_term; p = p->next) { | |
468 | + dump_memory_block(self, (unsigned char *) p + HEADER_SIZE); | |
469 | + } | |
470 | +} | |
471 | +#endif | |
472 | + |