source: mainline/uspace/lib/c/include/adt/generic_field.h@ a74d0ad

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a74d0ad was 5fe7692, checked in by Petr Koupy <petr.koupy@…>, 14 years ago

Removed side effects from map ADTs.

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
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
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32
33/** @file
34 * Generic type field.
35 */
36
37#ifndef LIBC_GENERIC_FIELD_H_
38#define LIBC_GENERIC_FIELD_H_
39
40#include <errno.h>
41#include <malloc.h>
42#include <mem.h>
43#include <unistd.h>
44
45/** Internal magic value for a&nbsp;field consistency check. */
46#define GENERIC_FIELD_MAGIC_VALUE 0x55667788
47
48/** Generic destructor function pointer. */
49#define DTOR_T(identifier) \
50 void (*identifier)(const void *)
51
52/** Generic type field declaration.
53 *
54 * @param[in] name Name of the field.
55 * @param[in] type Inner object type.
56 */
57#define GENERIC_FIELD_DECLARE(name, type) \
58 typedef struct name name##_t; \
59 \
60 struct name { \
61 int size; \
62 int next; \
63 type **items; \
64 int magic; \
65 }; \
66 \
67 int name##_add(name##_t *, type *); \
68 int name##_count(name##_t *); \
69 void name##_destroy(name##_t *, DTOR_T()); \
70 void name##_exclude_index(name##_t *, int, DTOR_T()); \
71 type **name##_get_field(name##_t *); \
72 type *name##_get_index(name##_t *, int); \
73 int name##_initialize(name##_t *); \
74 int name##_is_valid(name##_t *);
75
76/** Generic type field implementation.
77 *
78 * Should follow declaration with the same parameters.
79 *
80 * @param[in] name Name of the field.
81 * @param[in] type Inner object type.
82 */
83#define GENERIC_FIELD_IMPLEMENT(name, type) \
84 int name##_add(name##_t *field, type *value) \
85 { \
86 if (name##_is_valid(field)) { \
87 if (field->next == (field->size - 1)) { \
88 type **tmp; \
89 tmp = (type **) realloc(field->items, \
90 sizeof(type *) * 2 * field->size); \
91 if (!tmp) \
92 return ENOMEM; \
93 field->size *= 2; \
94 field->items = tmp; \
95 } \
96 field->items[field->next] = value; \
97 field->next++; \
98 field->items[field->next] = NULL; \
99 return field->next - 1; \
100 } \
101 return EINVAL; \
102 } \
103 \
104 int name##_count(name##_t *field) \
105 { \
106 return name##_is_valid(field) ? field->next : -1; \
107 } \
108 \
109 void name##_destroy(name##_t *field, DTOR_T(dtor)) \
110 { \
111 if (name##_is_valid(field)) { \
112 int index; \
113 field->magic = 0; \
114 if (dtor) { \
115 for (index = 0; index < field->next; index++) { \
116 if (field->items[index]) \
117 dtor(field->items[index]); \
118 } \
119 } \
120 free(field->items); \
121 } \
122 } \
123 \
124 void name##_exclude_index(name##_t *field, int index, DTOR_T(dtor)) \
125 { \
126 if (name##_is_valid(field) && (index >= 0) && \
127 (index < field->next) && (field->items[index])) { \
128 if (dtor) \
129 dtor(field->items[index]); \
130 field->items[index] = NULL; \
131 } \
132 } \
133 \
134 type *name##_get_index(name##_t *field, int index) \
135 { \
136 if (name##_is_valid(field) && (index >= 0) && \
137 (index < field->next) && (field->items[index])) \
138 return field->items[index]; \
139 return NULL; \
140 } \
141 \
142 type **name##_get_field(name##_t *field) \
143 { \
144 return name##_is_valid(field) ? field->items : NULL; \
145 } \
146 \
147 int name##_initialize(name##_t *field) \
148 { \
149 if (!field) \
150 return EINVAL; \
151 field->size = 2; \
152 field->next = 0; \
153 field->items = (type **) malloc(sizeof(type *) * field->size); \
154 if (!field->items) \
155 return ENOMEM; \
156 field->items[field->next] = NULL; \
157 field->magic = GENERIC_FIELD_MAGIC_VALUE; \
158 return EOK; \
159 } \
160 \
161 int name##_is_valid(name##_t *field) \
162 { \
163 return field && (field->magic == GENERIC_FIELD_MAGIC_VALUE); \
164 }
165
166#endif
167
168/** @}
169 */
Note: See TracBrowser for help on using the repository browser.