00001
00002
00003
00004
00005 #include <stdint.h>
00006 #include <u/libu.h>
00007 #include <toolbox/array.h>
00008
00009
00010 #ifndef SIZE_MAX
00011 #define SIZE_MAX ((size_t) -1)
00012 #endif
00013
00014 struct u_array_s
00015 {
00016 size_t nslots;
00017 u_array_type_t type;
00018 void *base;
00019 };
00020
00021 #define U_ARRAY_TYPE_IS_VALID(t) \
00022 (t > U_ARRAY_TYPE_UNSET && t <= U_ARRAY_TYPE_MAX)
00023
00024 static size_t sizeof_type[U_ARRAY_TYPE_MAX + 1] =
00025 {
00026 0,
00027 #ifdef HAVE__BOOL
00028 sizeof(_Bool),
00029 #endif
00030 sizeof(char),
00031 sizeof(unsigned char),
00032 sizeof(short),
00033 sizeof(unsigned short),
00034 sizeof(int),
00035 sizeof(unsigned int),
00036 sizeof(long),
00037 sizeof(unsigned long),
00038 #ifdef HAVE_LONG_LONG
00039 sizeof(long long),
00040 sizeof(unsigned long long),
00041 #endif
00042 #ifdef HAVE_INTMAX_T
00043 sizeof(intmax_t),
00044 sizeof(uintmax_t),
00045 #endif
00046 sizeof(float),
00047 sizeof(double),
00048 #ifdef HAVE_LONG_DOUBLE
00049 sizeof(long double),
00050 #endif
00051 #ifdef HAVE_FLOAT__COMPLEX
00052 sizeof(float _Complex),
00053 #endif
00054 #ifdef HAVE_DOUBLE__COMPLEX
00055 sizeof(double _Complex),
00056 #endif
00057 #ifdef HAVE_LONG_DOUBLE__COMPLEX
00058 sizeof(long double _Complex),
00059 #endif
00060 sizeof(void *)
00061 };
00062
00063 #define MAX_NSLOTS(da) (SIZE_MAX / sizeof_type[da->type])
00064
00135 int u_array_create (u_array_type_t t, size_t nslots, u_array_t **pda)
00136 {
00137 u_array_t *da = NULL;
00138 size_t max_nslots;
00139
00140 dbg_return_if (pda == NULL, -1);
00141 dbg_return_if (!U_ARRAY_TYPE_IS_VALID(t), -1);
00142
00143 da = u_zalloc(sizeof(u_array_t));
00144 warn_err_sif (da == NULL);
00145
00146 da->type = t;
00147
00148 if (nslots == 0)
00149 da->nslots = U_ARRAY_NSLOTS_DFL;
00150 else if (nslots > (max_nslots = MAX_NSLOTS(da)))
00151 da->nslots = max_nslots;
00152 else
00153 da->nslots = nslots;
00154
00155 da->base = u_zalloc(da->nslots * sizeof_type[da->type]);
00156 warn_err_sif (da->base == NULL);
00157
00158 *pda = da;
00159
00160 return 0;
00161 err:
00162 u_array_free(da);
00163 return -1;
00164 }
00165
00174 void u_array_free (u_array_t *da)
00175 {
00176 nop_return_if (da == NULL, );
00177
00178 U_FREE(da->base);
00179 u_free(da);
00180
00181 return;
00182 }
00183
00193 int u_array_resize (u_array_t *da, size_t idx)
00194 {
00195 void *new_base;
00196 size_t new_nslots, max_nslots;
00197
00198 dbg_return_if (da == NULL, -1);
00199
00200
00201 dbg_return_if (idx < da->nslots, 0);
00202
00203
00204 dbg_return_if (idx >= (max_nslots = MAX_NSLOTS(da)) - 1, -1);
00205
00206
00207 new_nslots = ((max_nslots - U_ARRAY_RESIZE_PAD - 1) >= idx) ?
00208 idx + U_ARRAY_RESIZE_PAD + 1 : max_nslots;
00209
00210
00211 new_base = u_realloc(da->base, new_nslots * sizeof_type[da->type]);
00212 warn_err_sif (new_base == NULL);
00213
00214 da->base = new_base;
00215 da->nslots = new_nslots;
00216
00217 return 0;
00218 err:
00219 return -1;
00220 }
00221
00226 #define U_ARRAY_GETSET_F(pfx, dtype, ctype) \
00227 int u_array_set##pfx (u_array_t *da, size_t idx, ctype v, ctype *pold) \
00228 { \
00229 ctype *ep; \
00230 \
00231 dbg_return_if (da == NULL, -1); \
00232 \
00233 \
00234 dbg_return_if (da->type != dtype, -1); \
00235 \
00236
00237 \
00238 if (idx > da->nslots - 1) \
00239 warn_err_if (u_array_resize(da, idx)); \
00240 \
00241 \
00242 ep = (ctype *) da->base + idx; \
00243 \
00244 \
00245 if (pold) \
00246 *pold = *ep; \
00247 \
00248 \
00249 *ep = v; \
00250 \
00251 return 0; \
00252 err: \
00253 return -1; \
00254 } \
00255 \
00256 int u_array_get##pfx (u_array_t *da, size_t idx, ctype *pv) \
00257 { \
00258 ctype *ep; \
00259 \
00260 dbg_return_if (da == NULL, -1); \
00261 dbg_return_if (pv == NULL, -1); \
00262 \
00263 dbg_return_if (da->type != dtype, -1); \
00264 \
00265 \
00266 warn_err_if (idx > da->nslots - 1); \
00267 \
00268 ep = (ctype *) da->base + idx; \
00269 \
00270 *pv = *ep; \
00271 \
00272 return 0; \
00273 err: \
00274 return -1; \
00275 }
00276
00277 U_ARRAY_GETSET_F(_char, U_ARRAY_TYPE_CHAR, char)
00278 U_ARRAY_GETSET_F(_u_char, U_ARRAY_TYPE_U_CHAR, unsigned char)
00279 U_ARRAY_GETSET_F(_short, U_ARRAY_TYPE_SHORT, short)
00280 U_ARRAY_GETSET_F(_u_short, U_ARRAY_TYPE_U_SHORT, unsigned short)
00281 U_ARRAY_GETSET_F(_int, U_ARRAY_TYPE_INT, int)
00282 U_ARRAY_GETSET_F(_u_int, U_ARRAY_TYPE_U_INT, unsigned int)
00283 U_ARRAY_GETSET_F(_long, U_ARRAY_TYPE_LONG, long)
00284 U_ARRAY_GETSET_F(_u_long, U_ARRAY_TYPE_U_LONG, unsigned long)
00285 U_ARRAY_GETSET_F(_float, U_ARRAY_TYPE_FLOAT, float)
00286 U_ARRAY_GETSET_F(_double, U_ARRAY_TYPE_DOUBLE, double)
00287
00288 #ifdef HAVE__BOOL
00289 U_ARRAY_GETSET_F(_bool, U_ARRAY_TYPE_BOOL, _Bool)
00290 #endif
00291
00292 #ifdef HAVE_LONG_LONG
00293 U_ARRAY_GETSET_F(_long_long, U_ARRAY_TYPE_LONG_LONG, long long)
00294 U_ARRAY_GETSET_F(_u_long_long, U_ARRAY_TYPE_U_LONG_LONG, unsigned long long)
00295 #endif
00296
00297 #ifdef HAVE_INTMAX_T
00298 U_ARRAY_GETSET_F(_intmax, U_ARRAY_TYPE_INTMAX, intmax_t)
00299 U_ARRAY_GETSET_F(_u_intmax, U_ARRAY_TYPE_U_INTMAX, uintmax_t)
00300 #endif
00301
00302 #ifdef HAVE_LONG_DOUBLE
00303 U_ARRAY_GETSET_F(_long_double, U_ARRAY_TYPE_LONG_DOUBLE, long double)
00304 #endif
00305
00306 #ifdef HAVE_FLOAT__COMPLEX
00307 U_ARRAY_GETSET_F(_float_complex, U_ARRAY_TYPE_FLOAT_COMPLEX, float _Complex)
00308 #endif
00309
00310 #ifdef HAVE_DOUBLE__COMPLEX
00311 U_ARRAY_GETSET_F(_double_complex, U_ARRAY_TYPE_DOUBLE_COMPLEX, double _Complex)
00312 #endif
00313
00314 #ifdef HAVE_LONG_DOUBLE__COMPLEX
00315 U_ARRAY_GETSET_F(_long_double_complex, U_ARRAY_TYPE_LONG_DOUBLE_COMPLEX, long double _Complex)
00316 #endif
00317
00356 void *u_array_set_ptr (u_array_t *da, size_t idx, void *v, int *prc)
00357 {
00358 void **ep, *old_ep;
00359
00360 dbg_err_if (da == NULL);
00361 dbg_err_if (da->type != U_ARRAY_TYPE_PTR);
00362
00363 if (idx > da->nslots - 1)
00364 dbg_err_if (u_array_resize (da, idx));
00365
00366 ep = (void **) da->base + idx;
00367
00368
00369 old_ep = *ep;
00370
00371
00372 *ep = v;
00373
00374 if (prc)
00375 *prc = 0;
00376
00377 return old_ep;
00378 err:
00379 if (prc)
00380 *prc = -1;
00381 return NULL;
00382 }
00383
00417 void *u_array_get_ptr (u_array_t *da, size_t idx, int *prc)
00418 {
00419 dbg_err_if (da == NULL);
00420 dbg_err_if (da->type != U_ARRAY_TYPE_PTR);
00421
00422 warn_err_if (idx > da->nslots - 1);
00423
00424 if (prc)
00425 *prc = 0;
00426
00427 return *((void **) da->base + idx);
00428 err:
00429 if (prc)
00430 *prc = -1;
00431 return NULL;
00432 }