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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 70ce016 was 820ab55c, checked in by Jakub Jermar <jakub@…>, 15 years ago

Cstyle fixes of generic field.

  • Property mode set to 100644
File size: 4.5 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 type field declaration.
49 *
50 * @param[in] name Name of the field.
51 * @param[in] type Inner object type.
52 */
53#define GENERIC_FIELD_DECLARE(name, type) \
54 typedef struct name name##_t; \
55 typedef name##_t *name##_ref; \
56 \
57 struct name { \
58 int size; \
59 int next; \
60 type **items; \
61 int magic; \
62 }; \
63 \
64 int name##_add(name##_ref, type *); \
65 int name##_count(name##_ref); \
66 void name##_destroy(name##_ref); \
67 void name##_exclude_index(name##_ref, int); \
68 type **name##_get_field(name##_ref); \
69 type *name##_get_index(name##_ref, int); \
70 int name##_initialize(name##_ref); \
71 int name##_is_valid(name##_ref);
72
73/** Generic type field implementation.
74 *
75 * Should follow declaration with the same parameters.
76 *
77 * @param[in] name Name of the field.
78 * @param[in] type Inner object type.
79 */
80#define GENERIC_FIELD_IMPLEMENT(name, type) \
81 int name##_add(name##_ref field, type *value) \
82 { \
83 if (name##_is_valid(field)) { \
84 if (field->next == (field->size - 1)) { \
85 type **tmp; \
86 tmp = (type **) realloc(field->items, \
87 sizeof(type *) * 2 * field->size); \
88 if (!tmp) \
89 return ENOMEM; \
90 field->size *= 2; \
91 field->items = tmp; \
92 } \
93 field->items[field->next] = value; \
94 ++field->next; \
95 field->items[field->next] = NULL; \
96 return field->next - 1; \
97 } \
98 return EINVAL; \
99 } \
100 \
101 int name##_count(name##_ref field) \
102 { \
103 return name##_is_valid(field) ? field->next : -1; \
104 } \
105 \
106 void name##_destroy(name##_ref field) \
107 { \
108 if (name##_is_valid(field)) { \
109 int index; \
110 field->magic = 0; \
111 for (index = 0; index < field->next; ++ index) { \
112 if (field->items[index]) \
113 free(field->items[index]); \
114 } \
115 free(field->items); \
116 } \
117 } \
118 \
119 void name##_exclude_index(name##_ref field, int index) \
120 { \
121 if (name##_is_valid(field) && (index >= 0) && \
122 (index < field->next) && (field->items[index])) { \
123 free(field->items[index]); \
124 field->items[index] = NULL; \
125 } \
126 } \
127 \
128 type *name##_get_index(name##_ref field, int index) \
129 { \
130 if (name##_is_valid(field) && (index >= 0) && \
131 (index < field->next) && (field->items[index])) \
132 return field->items[index]; \
133 return NULL; \
134 } \
135 \
136 type **name##_get_field(name##_ref field) \
137 { \
138 return name##_is_valid(field) ? field->items : NULL; \
139 } \
140 \
141 int name##_initialize(name##_ref field) \
142 { \
143 if (!field) \
144 return EINVAL; \
145 field->size = 2; \
146 field->next = 0; \
147 field->items = (type **) malloc(sizeof(type *) * field->size); \
148 if (!field->items) \
149 return ENOMEM; \
150 field->items[field->next] = NULL; \
151 field->magic = GENERIC_FIELD_MAGIC_VALUE; \
152 return EOK; \
153 } \
154 \
155 int name##_is_valid(name##_ref field) \
156 { \
157 return field && (field->magic == GENERIC_FIELD_MAGIC_VALUE); \
158 }
159
160#endif
161
162/** @}
163 */
Note: See TracBrowser for help on using the repository browser.