buf, array
@@ -1,8 +1,9 @@ | ||
1 | 1 | all: libnpl.a |
2 | 2 | |
3 | -libnpl.a: npl.o object.o stream.o str.o mbstr.o type.o sbuf.o | |
3 | +libnpl.a: npl.o object.o stream.o str.o mbstr.o type.o sbuf.o \ | |
4 | +array.o buf.o | |
4 | 5 | ar rcs libnpl.a npl.o object.o stream.o str.o \ |
5 | - mbstr.o type.o sbuf.o | |
6 | + mbstr.o type.o sbuf.o array.o buf.o | |
6 | 7 | |
7 | 8 | npl.o: npl.c npl.h global.h |
8 | 9 | gcc -c npl.c |
@@ -25,6 +26,12 @@ | ||
25 | 26 | sbuf.o: sbuf.c npl.h global.h |
26 | 27 | gcc -c sbuf.c |
27 | 28 | |
29 | +array.o: array.c npl.h global.h | |
30 | + gcc -c array.c | |
31 | + | |
32 | +buf.o: buf.c npl.h global.h | |
33 | + gcc -c buf.c | |
34 | + | |
28 | 35 | clean: |
29 | 36 | rm -f *.o |
30 | 37 | rm -f libnpl.a |
@@ -0,0 +1,115 @@ | ||
1 | +#include "global.h" | |
2 | + | |
3 | +static int _change_buf(npl_array_t *a, size_t len) | |
4 | +{ | |
5 | + size_t bytes; | |
6 | + | |
7 | + if (a->size != 0) { | |
8 | + if (len > (SIZE_MAX / a->size)) | |
9 | + return 1; // error | |
10 | + bytes = len * a->size; | |
11 | + if (npl_buf_resize(&a->buf, bytes)) | |
12 | + return 1; // error | |
13 | + } | |
14 | + a->len = len; | |
15 | + | |
16 | + return 0; | |
17 | +} | |
18 | + | |
19 | +int npl_array_init(npl_array_t *a, size_t size, size_t len) | |
20 | +{ | |
21 | + assert(a); | |
22 | + if (npl_buf_init(&a->buf, 0)) | |
23 | + return 1; // error | |
24 | + a->size = size; | |
25 | + a->len = 0; | |
26 | + return _change_buf(a, len); | |
27 | +} | |
28 | + | |
29 | +npl_array_t* npl_array_new(size_t size, size_t len) | |
30 | +{ | |
31 | + npl_object_t *object; | |
32 | + | |
33 | + object = npl_object_new(npl_array_type); | |
34 | + if (object == NULL) | |
35 | + return NULL; | |
36 | + if (npl_array_init(NPL_ARRAY(object), size, len)) { | |
37 | + npl_object_unref(object); | |
38 | + return NULL; | |
39 | + } | |
40 | + | |
41 | + return NPL_ARRAY(object); | |
42 | +} | |
43 | + | |
44 | +int npl_array_set(npl_array_t *a, size_t i, void *e) | |
45 | +{ | |
46 | + void *p; | |
47 | + | |
48 | + assert(a); | |
49 | + assert(e); | |
50 | + | |
51 | + // バッファを増やす | |
52 | + if (i >= a->len) { | |
53 | + int res; | |
54 | + size_t n; | |
55 | + | |
56 | + n = i + 1; | |
57 | + if (n < 1) | |
58 | + return 1; // error | |
59 | + res = _change_buf(a, n); | |
60 | + if (res) | |
61 | + return 1; // error | |
62 | + } | |
63 | + | |
64 | + // 指定の要素にデータをコピー | |
65 | + p = npl_array_get(a, i); | |
66 | + if (p == NULL) | |
67 | + return 1; // error; | |
68 | + memcpy(p, e, a->size); | |
69 | + | |
70 | + return 0; | |
71 | +} | |
72 | + | |
73 | +void* npl_array_get(npl_array_t *a, size_t i) | |
74 | +{ | |
75 | + unsigned char *p; | |
76 | + | |
77 | + assert(a); | |
78 | + if (a->buf.buf == NULL) | |
79 | + return NULL; | |
80 | + if (i >= a->len) | |
81 | + return NULL; | |
82 | + if (a->size == 0) | |
83 | + return NULL; | |
84 | + | |
85 | + p = a->buf.buf; | |
86 | + | |
87 | + return (p + (a->size * i)); | |
88 | +} | |
89 | + | |
90 | +size_t npl_array_size(npl_array_t *a) | |
91 | +{ | |
92 | + assert(a); | |
93 | + return a->size; | |
94 | +} | |
95 | + | |
96 | +size_t npl_array_len(npl_array_t *a) | |
97 | +{ | |
98 | + assert(a); | |
99 | + return a->len; | |
100 | +} | |
101 | + | |
102 | +npl_type_t _npl_array_type = { | |
103 | + .object = { | |
104 | + .type = &_npl_type_type, | |
105 | + .ref_count = 0, | |
106 | + .static_flag = 1, | |
107 | + }, | |
108 | + .name = L"Array", | |
109 | + .destructor = NULL, | |
110 | + .parent = &_npl_buf_type, | |
111 | + .size = sizeof(npl_array_t), | |
112 | +}; | |
113 | + | |
114 | +npl_type_t *npl_array_type = &_npl_array_type; | |
115 | + |
@@ -0,0 +1,105 @@ | ||
1 | +#include "global.h" | |
2 | + | |
3 | +int npl_buf_init(npl_buf_t *buf, size_t bytes) | |
4 | +{ | |
5 | + assert(buf); | |
6 | + return npl_buf_resize(buf, bytes); | |
7 | +} | |
8 | + | |
9 | +npl_buf_t* npl_buf_new(size_t bytes) | |
10 | +{ | |
11 | + npl_object_t *object; | |
12 | + | |
13 | + object = npl_object_new(npl_buf_type); | |
14 | + if (object == NULL) | |
15 | + return NULL; | |
16 | + if (npl_buf_init(NPL_BUF(object), bytes)) { | |
17 | + npl_object_unref(object); | |
18 | + return NULL; | |
19 | + } | |
20 | + | |
21 | + return NPL_BUF(object); | |
22 | +} | |
23 | + | |
24 | +size_t npl_buf_size(npl_buf_t *buf) | |
25 | +{ | |
26 | + assert(buf); | |
27 | + return buf->bytes; | |
28 | +} | |
29 | + | |
30 | +void* npl_buf_get(npl_buf_t *buf) | |
31 | +{ | |
32 | + assert(buf); | |
33 | + return buf->buf; | |
34 | +} | |
35 | + | |
36 | +int npl_buf_resize(npl_buf_t *buf, size_t bytes) | |
37 | +{ | |
38 | + assert(buf); | |
39 | + | |
40 | + // サイズが 0 ならば、バッファ無しにする | |
41 | + if (bytes == 0) { | |
42 | + buf->bytes = 0; | |
43 | + if (buf->buf != NULL) { | |
44 | + free(buf->buf); | |
45 | + buf->buf = NULL; | |
46 | + } | |
47 | + return 0; | |
48 | + } | |
49 | + | |
50 | + // バッファを新たに作成か、サイズ変更する | |
51 | + if (buf->buf == NULL) { | |
52 | + buf->buf = malloc(bytes); | |
53 | + if (buf->buf == NULL) | |
54 | + return 1; // error | |
55 | + buf->bytes = bytes; | |
56 | + memset(buf->buf, 0, bytes); | |
57 | + } else { | |
58 | + unsigned char *p; | |
59 | + | |
60 | + p = realloc(buf->buf, bytes); | |
61 | + if (p == NULL) | |
62 | + return 1; // error | |
63 | + | |
64 | + // サイズが以前より大きいならば、 | |
65 | + // 増えた分のバッファをゼロで | |
66 | + // 初期化する。 | |
67 | + if (bytes > buf->bytes) { | |
68 | + size_t rest; | |
69 | + | |
70 | + rest = bytes - buf->bytes; | |
71 | + memset(&p[buf->bytes], 0, rest); | |
72 | + } | |
73 | + | |
74 | + buf->buf = p; | |
75 | + buf->bytes = bytes; | |
76 | + } | |
77 | + | |
78 | + return 0; | |
79 | +} | |
80 | + | |
81 | +static void _destructor(npl_object_t *object) | |
82 | +{ | |
83 | + npl_buf_t *buf = NPL_BUF(object); | |
84 | + | |
85 | + if (buf->buf != NULL) { | |
86 | + free(buf->buf); | |
87 | + buf->buf = NULL; | |
88 | + } | |
89 | + buf->bytes = 0; | |
90 | +} | |
91 | + | |
92 | +npl_type_t _npl_buf_type = { | |
93 | + .object = { | |
94 | + .type = &_npl_type_type, | |
95 | + .ref_count = 0, | |
96 | + .static_flag = 1, | |
97 | + }, | |
98 | + .name = L"Buffer", | |
99 | + .destructor = _destructor, | |
100 | + .parent = &_npl_object_type, | |
101 | + .size = sizeof(npl_buf_t), | |
102 | +}; | |
103 | + | |
104 | +npl_type_t *npl_buf_type = &_npl_buf_type; | |
105 | + |
@@ -11,6 +11,8 @@ | ||
11 | 11 | // 型キャストマクロ |
12 | 12 | #define NPL_OBJECT(x) _NPL_CAST(npl_object_t, x, npl_object_type) |
13 | 13 | #define NPL_TYPE(x) _NPL_CAST(npl_type_t, x, npl_type_type) |
14 | +#define NPL_BUF(x) _NPL_CAST(npl_buf_t, x, npl_buf_type) | |
15 | +#define NPL_ARRAY(x) _NPL_CAST(npl_array_t, x, npl_array_type) | |
14 | 16 | #define NPL_STR(x) _NPL_CAST(npl_str_t, x, npl_str_type) |
15 | 17 | #define NPL_MBSTR(x) _NPL_CAST(npl_mbstr_t, x, npl_mbstr_type) |
16 | 18 | #define NPL_SBUF(x) _NPL_CAST(npl_sbuf_t, x, npl_sbuf_type) |
@@ -19,6 +21,8 @@ | ||
19 | 21 | // typedef |
20 | 22 | typedef struct npl_object_t npl_object_t; |
21 | 23 | typedef struct npl_type_t npl_type_t; |
24 | +typedef struct npl_buf_t npl_buf_t; | |
25 | +typedef struct npl_array_t npl_array_t; | |
22 | 26 | typedef struct npl_str_t npl_str_t; |
23 | 27 | typedef struct npl_mbstr_t npl_mbstr_t; |
24 | 28 | typedef struct npl_sbuf_t npl_sbuf_t; |
@@ -33,18 +37,22 @@ | ||
33 | 37 | // 静的な型 |
34 | 38 | extern npl_type_t _npl_object_type; |
35 | 39 | extern npl_type_t _npl_type_type; |
40 | +extern npl_type_t _npl_buf_type; | |
41 | +extern npl_type_t _npl_array_type; | |
36 | 42 | extern npl_type_t _npl_str_type; |
37 | 43 | extern npl_type_t _npl_mbstr_type; |
44 | +extern npl_type_t _npl_sbuf_type; | |
38 | 45 | extern npl_type_t _npl_stream_type; |
39 | 46 | |
40 | 47 | extern npl_type_t *npl_object_type; |
41 | 48 | extern npl_type_t *npl_type_type; |
49 | +extern npl_type_t *npl_buf_type; | |
50 | +extern npl_type_t *npl_array_type; | |
42 | 51 | extern npl_type_t *npl_str_type; |
43 | 52 | extern npl_type_t *npl_mbstr_type; |
53 | +extern npl_type_t *npl_sbuf_type; | |
44 | 54 | extern npl_type_t *npl_stream_type; |
45 | 55 | |
46 | -extern npl_type_t *npl_sbuf_type; | |
47 | - | |
48 | 56 | // object class |
49 | 57 | struct npl_object_t { |
50 | 58 | npl_type_t *type; |
@@ -85,6 +93,43 @@ | ||
85 | 93 | const char *func_name, |
86 | 94 | unsigned int line_no); |
87 | 95 | |
96 | +// buf class | |
97 | +// サイズ変更可能な単純データ領域 | |
98 | +struct npl_buf_t { | |
99 | + npl_object_t object; | |
100 | + | |
101 | + // バイト数 | |
102 | + size_t bytes; | |
103 | + | |
104 | + // バッファ | |
105 | + void *buf; | |
106 | +}; | |
107 | + | |
108 | +int npl_buf_init(npl_buf_t *buf, size_t bytes); | |
109 | +npl_buf_t* npl_buf_new(size_t bytes); | |
110 | +size_t npl_buf_size(npl_buf_t *buf); | |
111 | +void* npl_buf_get(npl_buf_t *buf); | |
112 | +int npl_buf_resize(npl_buf_t *buf, size_t bytes); | |
113 | + | |
114 | +// array class | |
115 | +// 配列 | |
116 | +struct npl_array_t { | |
117 | + npl_buf_t buf; | |
118 | + | |
119 | + // 配列要素のサイズ | |
120 | + size_t size; | |
121 | + | |
122 | + // 現在の配列の要素数 | |
123 | + size_t len; | |
124 | +}; | |
125 | + | |
126 | +int npl_array_init(npl_array_t *a, size_t size, size_t len); | |
127 | +npl_array_t* npl_array_new(size_t size, size_t len); | |
128 | +int npl_array_set(npl_array_t *a, size_t i, void *e); | |
129 | +void* npl_array_get(npl_array_t *a, size_t i); | |
130 | +size_t npl_array_size(npl_array_t *a); | |
131 | +size_t npl_array_len(npl_array_t *a); | |
132 | + | |
88 | 133 | // str class |
89 | 134 | // str はワイド文字の文字列。 |
90 | 135 | npl_str_t* npl_str_new(const wchar_t *s); |
@@ -121,10 +121,13 @@ | ||
121 | 121 | static void _destructor(npl_object_t *object) |
122 | 122 | { |
123 | 123 | npl_sbuf_t *sb = NPL_SBUF(object); |
124 | - free(sb->buf); | |
124 | + if (sb->buf != NULL) { | |
125 | + free(sb->buf); | |
126 | + sb->buf = NULL; | |
127 | + } | |
125 | 128 | } |
126 | 129 | |
127 | -static npl_type_t _npl_sbuf_type = { | |
130 | +npl_type_t _npl_sbuf_type = { | |
128 | 131 | .object = { |
129 | 132 | .type = &_npl_type_type, |
130 | 133 | .ref_count = 0, |
@@ -1,4 +1,4 @@ | ||
1 | -all: init hello strbuf echo string | |
1 | +all: init hello strbuf echo string ary | |
2 | 2 | |
3 | 3 | init: init.c |
4 | 4 | gcc -oinit init.c ../libnpl.a |
@@ -15,6 +15,9 @@ | ||
15 | 15 | string: string.c |
16 | 16 | gcc -ostring string.c ../libnpl.a |
17 | 17 | |
18 | +ary: ary.c | |
19 | + gcc -oary ary.c ../libnpl.a | |
20 | + | |
18 | 21 | clean: |
19 | 22 | rm -f init |
20 | 23 | rm -f hello |
@@ -21,4 +24,5 @@ | ||
21 | 24 | rm -f strbuf |
22 | 25 | rm -f echo |
23 | 26 | rm -f string |
27 | + rm -f ary | |
24 | 28 |
@@ -0,0 +1,55 @@ | ||
1 | +/* ary.c | |
2 | + * | |
3 | + * 配列 (npl_array_t) のテスト | |
4 | + */ | |
5 | + | |
6 | +#include <stdio.h> | |
7 | +#include <stdlib.h> | |
8 | +#include "../npl.h" | |
9 | + | |
10 | +int main() | |
11 | +{ | |
12 | + npl_array_t *a; | |
13 | + double d, *p; | |
14 | + int i; | |
15 | + | |
16 | + // NPLライブラリ初期化 | |
17 | + if (npl_init()) { | |
18 | + fprintf(stderr, "npl_init() failed.\n"); | |
19 | + exit(1); | |
20 | + } | |
21 | + | |
22 | + a = npl_array_new(sizeof(double), 2); | |
23 | + if (a == NULL) { | |
24 | + fprintf(stderr, "npl_array_new() failed.\n"); | |
25 | + exit(1); | |
26 | + } | |
27 | + | |
28 | + d = 1.0; | |
29 | + for (i=0; i<7; i++) { | |
30 | + if (npl_array_set(a, i, &d)) { | |
31 | + fprintf(stderr, "npl_array_set() failed.\n"); | |
32 | + exit(1); | |
33 | + } | |
34 | + d += 0.01; | |
35 | + } | |
36 | + | |
37 | + for (i=0; i<npl_array_len(a); i++) { | |
38 | + p = npl_array_get(a, i); | |
39 | + if (p != NULL) | |
40 | + printf("%f\n", *p); | |
41 | + else | |
42 | + printf("--\n"); | |
43 | + } | |
44 | + | |
45 | + npl_object_unref(NPL_OBJECT(a)); | |
46 | + | |
47 | + // NPLライブラリ終了処理 | |
48 | + if (npl_final()) { | |
49 | + fprintf(stderr, "npl_final() failed.\n"); | |
50 | + exit(1); | |
51 | + } | |
52 | + | |
53 | + return 0; | |
54 | +} | |
55 | + |